8.2.2继承 第8章 面向对象编程简介
2014-10-30 21:30
141 查看
继承是OOP最重要的特性之一。 OOP--面向对象
任何类都可以从另一个类中继承,这就是说,这个类拥有它继承的类的所有成员。在OOP中,被继承(继承也称为派生)的类称为父类(也称为基类)。注意,C#中的对象仅能直接派生于一个基类,当然基类也可以由自己的基类。
继承性可以从一个较一般的基类扩展或创建更多的特定类。例如,考虑一个代表农场家畜的类。这个类叫做Animal,拥有方法如EatFood()或Breed(),我们可以创建一个派生类Cow,支持所有这些方法,它也有自己的方法,如Moo()和SupplyMilk()。还可以创建另外一个派生类Chicken,该类有Cluck()和LayEgg()方法。
在继承一个基类时,成员的可访问性就成了一个重要问题。派生类不能访问基类的私有成员,但可以访问其公共成员。不过,派生类和外部的代码都可以访问公共成员。这就是说,只使用这两个可访问性,不能让一个成员只让基类和派生类访问,而不能由外部代码访问。
为了解决这个问题,C#提供了第三种可访问性protected,只有派生类才可以访问protected成员。对外部代码来说,这个可访问性与私有成员一样:外部代码不能访问private成员和protected成员。
除了定义成员的保护级别外,我们还可以为成员定义其继承行为。基类的成员可以是virtual的,也就是说,成员可以由继承它的类重写。派生类可以提供成员的其他执行代码。这种执行代码不会删除原来的代码,仍可以在类中访问原来的代码,但是外部不能访问它们。如果没有提供其他执行方式,外部代码就可以访问基类中成员的执行代码。
注意:虚拟成员不能是私有成员,因为这样会自相矛盾——不能说成员可以由派生类重写,同时派生类又不能访问它。
在前面的家畜示例中,可以把EatFood变成虚拟成员,在派生类中为它提供新的执行代码,例如为Cow类提供新执行代码,如下图所示。
这里显示了Animal和Cow类的EatFood()方法,说明它们有自己的执行代码。
基类还可以定义为抽象类,抽象类不能直接实例化。要使用抽象类,必须继承这个类,抽象类可以有抽象成员,这些成员在基类中没有指定代码,这些执行代码必须在派生类中提供。
如果Animal是一个抽象类,UML图就会如下图所示
注意:抽象类以斜体名称显示(有时它们的方框是虚线)
上图中EatFood()和Breed()都显示在派生类Chicken和Cow中。
有两种可能:
1.说明这些方法是抽象的(必须在派生类中重写)
2.说明这些方法是虚拟的(已紧在Chicken和Cow中重写)
当然,抽象基类可以提供成员的实现代码,这是很常见的。不能实例化抽象类,意味着不能再抽象类中封装功能。
最后,类可以是密封的sealed。密封的类不能用作基类,所以没有派生类。
在C#中,所有的对象都有一个共同的基类object(在.Net Framework中,其别名是System.Object)。第9章中将详细介绍这个类。
注意:如本章前面所述,接口也可以继承自其他接口。与类不同的是,接口可以继承多个基接口(以类可以支持多个接口的方式派生)
任何类都可以从另一个类中继承,这就是说,这个类拥有它继承的类的所有成员。在OOP中,被继承(继承也称为派生)的类称为父类(也称为基类)。注意,C#中的对象仅能直接派生于一个基类,当然基类也可以由自己的基类。
继承性可以从一个较一般的基类扩展或创建更多的特定类。例如,考虑一个代表农场家畜的类。这个类叫做Animal,拥有方法如EatFood()或Breed(),我们可以创建一个派生类Cow,支持所有这些方法,它也有自己的方法,如Moo()和SupplyMilk()。还可以创建另外一个派生类Chicken,该类有Cluck()和LayEgg()方法。
在继承一个基类时,成员的可访问性就成了一个重要问题。派生类不能访问基类的私有成员,但可以访问其公共成员。不过,派生类和外部的代码都可以访问公共成员。这就是说,只使用这两个可访问性,不能让一个成员只让基类和派生类访问,而不能由外部代码访问。
为了解决这个问题,C#提供了第三种可访问性protected,只有派生类才可以访问protected成员。对外部代码来说,这个可访问性与私有成员一样:外部代码不能访问private成员和protected成员。
除了定义成员的保护级别外,我们还可以为成员定义其继承行为。基类的成员可以是virtual的,也就是说,成员可以由继承它的类重写。派生类可以提供成员的其他执行代码。这种执行代码不会删除原来的代码,仍可以在类中访问原来的代码,但是外部不能访问它们。如果没有提供其他执行方式,外部代码就可以访问基类中成员的执行代码。
注意:虚拟成员不能是私有成员,因为这样会自相矛盾——不能说成员可以由派生类重写,同时派生类又不能访问它。
在前面的家畜示例中,可以把EatFood变成虚拟成员,在派生类中为它提供新的执行代码,例如为Cow类提供新执行代码,如下图所示。
这里显示了Animal和Cow类的EatFood()方法,说明它们有自己的执行代码。
基类还可以定义为抽象类,抽象类不能直接实例化。要使用抽象类,必须继承这个类,抽象类可以有抽象成员,这些成员在基类中没有指定代码,这些执行代码必须在派生类中提供。
如果Animal是一个抽象类,UML图就会如下图所示
注意:抽象类以斜体名称显示(有时它们的方框是虚线)
上图中EatFood()和Breed()都显示在派生类Chicken和Cow中。
有两种可能:
1.说明这些方法是抽象的(必须在派生类中重写)
abstract class Animal { public abstract void EadFood();//抽象方法,不可以有{}主体 public abstract void Breed(); } class Cow : Animal { public void Moo() { } public void SupplyMilk() { } public override void EadFood() { }//抽象方法在子类中必须实现 public override void Breed() { } } class Chicken : Animal { public void Cluck() { } public void LayEgg() { } public override void EadFood() { } public override void Breed() { } }
2.说明这些方法是虚拟的(已紧在Chicken和Cow中重写)
abstract class Animal { public virtual void EadFood() { }//虚拟方法,必须有{}实体 public virtual void Breed() { } } class Cow : Animal { public void Moo() { } public void SupplyMilk() { } public override void EadFood() { }//虚拟方法在子类中可以实现,也可以不实现 public override void Breed() { } } class Chicken : Animal { public void Cluck() { } public void LayEgg() { } public override void EadFood() { } public override void Breed() { } }
当然,抽象基类可以提供成员的实现代码,这是很常见的。不能实例化抽象类,意味着不能再抽象类中封装功能。
最后,类可以是密封的sealed。密封的类不能用作基类,所以没有派生类。
在C#中,所有的对象都有一个共同的基类object(在.Net Framework中,其别名是System.Object)。第9章中将详细介绍这个类。
注意:如本章前面所述,接口也可以继承自其他接口。与类不同的是,接口可以继承多个基接口(以类可以支持多个接口的方式派生)
相关文章推荐
- 8.2.3多态性 第8章 面向对象编程简介
- 第8章 面向对象编程简介
- (原创)c#学习笔记08--面向对象编程简介02--OOP技术02--继承
- Javascript面向对象编程(三):非构造函数的继承
- 面向对象编程,继承
- 我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
- Javascript面向对象编程(二):构造函数的继承
- Javascript面向对象编程(二):构造函数的继承
- js面向对象编程—继承
- C# 面向对象编程之封装、继承、多态 <思维导图>
- 用C进行面向对象编程 (用C模拟继承,多态)
- JS面向对象编程之:封装、继承、多态
- Javascript面向对象编程(三):非构造函数的继承
- C++ Primer 学习笔记_67_面向对象编程 -变换与继承、复制控制与继承
- (原创)c#学习笔记08--面向对象编程简介01--面向对象编程的含义01--对象的含义02--方法
- (原创)c#学习笔记08--面向对象编程简介02--OOP技术04--对象之间的关系
- js原生设计模式——2面向对象编程之继承—call(this)构造函数式继承
- Javascript面向对象编程(三):非构造函数的继承
- Javascript面向对象编程(二):构造函数的继承
- C#继承小结——面向对象编程的三大机制之一