F#入门-第四章 面向对象-第五节 继承
2010-09-21 13:03
183 查看
■ 应该使用继承的场合
继承是指以现有的类(父类)为基础,定义新类(子类)。子类继承父类的所有功能,可以对父类的功能进行改写,可以追加新的功能。继承的功用是十分强大的,但是如果使用不得当的话,会使程序设计变得非常奇怪,所以首先让我们来看应该使用继承的正确场合。
通过继承,子类继承了父类的全部功能,也就是说,子类可以说是父类的一种,这里是重点,一般说来只有当“子类就是父类的一种”这种关系成立的时候,才应该使用继承。
拿汽车来举例说明,“公共汽车是汽车的一种“,“小轿车是汽车的一种“,这种说法是正确的,所以公共汽车类或小轿车类继承汽车类是不会有什么问题的。但是,“轮胎是汽车的一种“这种说法是错误的,所以轮胎类继承汽车类是不正确的。
这种“A是B的一种”的关系在面向对象的专门术语种叫做“is-a关系”,谈到继承的原则时,只有“is-a关系”成立时才应该进行继承。同时,“A具有B"这种关系叫做"has-a关系"。上例中,因为可以说“汽车具有轮胎”,所以汽车和轮胎的关系是"has-a关系",当这种"has-a关系"成立时不应该使用继承,而应该使用聚合或复合的技术,这样才能很好地进行程序设计。关于聚合与复合,在后文详述。
■ 继承
F#的继承与Java和C#语言中的继承一样,只支持单父类(与接口)继承。这恐怕是因为多父类继承(多重继承)会产生譬如菱形继承等各种各样问题的缘故。
类的继承的书写方法为在class关键字后加inherit关键字,然后指定父类。
首先,创建父类。
准备:父类的定义
上例中创建了老鼠类。就象例子中记述的那样,该类只具有名字。接着,我们创建一个继承该类并具有口袋的老鼠类。
类的继承
上例中创建了继承mouse类的pocketmouse类。pocketmouse类继承了mouse类的全部成员,所以也具有没有特别声明的name字段。
class inherit mouse的部分为实现继承的部分,利用该表达式声明mouse类的继承。同时,在构造器的初始化的位置,调用父类的构造器,调用时使用inherit关键字。
创建类时,知道父类与子类的构造器的调用顺序是十分有用的。接下来的例子中,确认构造器的调用顺序。
构造器的调用顺序
正如下面执行结果所示,首先调用基本类的构造器。
执行结果
另外,在子类的构造器的初始化的部分,不想显式调用父类的构造器的时候,可以使用()作为参数来调用构造器。
简化了初始化的构造器
其执行结果与前面的执行结果相同。
执行结果
正如下例所示,当没有接受()作为参数的构造器时,会产生编译错误。
没有接受()作为参数的构造器时会产生编译错误
最后,使用默认的构造器,书写的程序如下所示。
默认的构造器
这种情况下,调用父类的构造器时的参数是在用inherit关键字声明父类时一起指定的。
继承是指以现有的类(父类)为基础,定义新类(子类)。子类继承父类的所有功能,可以对父类的功能进行改写,可以追加新的功能。继承的功用是十分强大的,但是如果使用不得当的话,会使程序设计变得非常奇怪,所以首先让我们来看应该使用继承的正确场合。
通过继承,子类继承了父类的全部功能,也就是说,子类可以说是父类的一种,这里是重点,一般说来只有当“子类就是父类的一种”这种关系成立的时候,才应该使用继承。
拿汽车来举例说明,“公共汽车是汽车的一种“,“小轿车是汽车的一种“,这种说法是正确的,所以公共汽车类或小轿车类继承汽车类是不会有什么问题的。但是,“轮胎是汽车的一种“这种说法是错误的,所以轮胎类继承汽车类是不正确的。
这种“A是B的一种”的关系在面向对象的专门术语种叫做“is-a关系”,谈到继承的原则时,只有“is-a关系”成立时才应该进行继承。同时,“A具有B"这种关系叫做"has-a关系"。上例中,因为可以说“汽车具有轮胎”,所以汽车和轮胎的关系是"has-a关系",当这种"has-a关系"成立时不应该使用继承,而应该使用聚合或复合的技术,这样才能很好地进行程序设计。关于聚合与复合,在后文详述。
■ 继承
F#的继承与Java和C#语言中的继承一样,只支持单父类(与接口)继承。这恐怕是因为多父类继承(多重继承)会产生譬如菱形继承等各种各样问题的缘故。
类的继承的书写方法为在class关键字后加inherit关键字,然后指定父类。
首先,创建父类。
准备:父类的定义
type Mouse = class val name : string new (n) = {name = n} end;; let hatuka = new Mouse("Hatuka nezumi");; |
类的继承
type PocketMouse = class inherit Mouse val pocket : string new (namae,contents) = {inherit Mouse(namae);pocket = contents;} end;; let dora = new PocketMouse("doraemon","4jigen pocket");; let pika = new PocketMouse("pikachu","denki bukuro");; |
class inherit mouse的部分为实现继承的部分,利用该表达式声明mouse类的继承。同时,在构造器的初始化的位置,调用父类的构造器,调用时使用inherit关键字。
创建类时,知道父类与子类的构造器的调用顺序是十分有用的。接下来的例子中,确认构造器的调用顺序。
构造器的调用顺序
type Mouse = class val name : string new (n) = {name = n} then System.Console.WriteLine("base class constructor called") end;; type PocketMouse = class inherit Mouse val pocket : string new (namae,contents) = {inherit Mouse(namae);pocket = contents;} then System.Console.WriteLine("sub class constructor called"); end;; let dora = new PocketMouse("doraemon","4jigen pocket");; |
执行结果
base class constructor called sub class constructor called 按任何键继续 . . . |
简化了初始化的构造器
type Mouse = class val name : string new () = {name = "nezumi"} then System.Console.WriteLine("base class constructor called") end;; type PocketMouse = class inherit Mouse val pocket : string new (contents) = {pocket = contents;} then System.Console.WriteLine("sub class constructor called"); end;; let dora = new PocketMouse("4jigen pocket");; |
执行结果
base class constructor called sub class constructor called 按任何键继续 . . . |
没有接受()作为参数的构造器时会产生编译错误
type Mouse = class val name : string new (n) = {name = n} then System.Console.WriteLine("base class constructor called") end;; type PocketMouse = class inherit Mouse val pocket : string new (contents) = {pocket = contents;} then System.Console.WriteLine("sub class constructor called"); end;; let dora = new PocketMouse("4jigen pocket");; |
默认的构造器
type Mouse(n) = class member x.name = n : string end;; type PocketMouse(n,contents) = class inherit Mouse(n) member x.pocket = contents : string end;; let dora = new PocketMouse("doraemon","4jigen pocket");; |
相关文章推荐
- F#入门-第四章 面向对象-第三节 成员函数
- F#入门-第四章 面向对象-第四节 封装
- F#入门-第四章 面向对象-第七节 接口
- F#入门-第四章 面向对象-第八节 对象表达式
- F#入门-第四章 面向对象-第十一节 活动模式
- F#入门-第四章 面向对象-第二节 类与构造器
- F#入门-第四章 面向对象-第一节 对象
- Java 入门 之 面向对象 封装、继承与多态(二)
- VC++入门经典学习笔记--继承和面向对象
- C#面向对象(OOP)入门—第一天—多态和继承(方法重载)
- Java 入门 之 面向对象 封装、继承与多态(一)
- F#入门-第四章 面向对象-第九节 索引器
- F#入门-第四章 面向对象-第六节 重载
- PHP入门教程之面向对象的特性分析(继承,多态,接口,抽象类,抽象方法等)
- C#面向对象(OOP)入门—第二天—多态和继承(继承)
- C#面向对象(OOP)入门—第二天—多态和继承(继承)
- JAVA菜鸟入门篇 - 面向对象三大特征之一:继承 ,方法重写(override)和Object类 (十四)
- C#编程入门10_面向对象之继承
- Python一天入门16:面向对象的编程3-继承
- Java入门笔记-(面向对象:封装,多态,继承)