本文是深刻浅出OOP第二篇,主要说说继承的话题。html
深刻理解OOP(四):多态和继承(C#中的抽象类)spa
深刻理解OOP(五):C#中的访问修饰符(Public/Private/Protected/Internal/Sealed/Constants/Static and Readonly Fields)设计
深刻理解OOP(六):枚举(实用方法)code
深刻理解OOP(七):属性(实用方法)orm
深刻理解OOP(八):索引器(实用方法)htm
深刻理解OOP(九):事件(深刻理解)对象
建立一个Console工程,命名为InheritanceAndPolymorphism。添加ClassA、ClassB类,并拷贝下面的代码:
ClassA: class ClassA { } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
在Program.cs中,调用ClassA
class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); } }
若是运行,确定会报错的。
Error:
'InheritanceAndPolymorphism.ClassA
' does not contain a definition for 'Display1
' and no extension method 'Display1
' accepting a first argument of type 'InheritanceAndPolymorphism.ClassA
' could be found
由于咱们在ClassA中未定义Display1的方法。 下面咱们重写,使ClassA继承自ClassB。
ClassA: class ClassA:ClassB { } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
再次运行,结果以下:
ClassB Display1
ClassA已经能够访问其基类的Display1函数了,这个简单的实例说明了继承可复用基类的妙处,下面这张图以父子财产继承关系说明了继承的意义。
再来看另一个场景,假设ClassA也有一个Display1函数,签名和其基类同样的:
class ClassA:ClassB { public void Display1() { System.Console.WriteLine("ClassA Display1"); } } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
执行后结果以下:
ClassA Display1
看起来结果是对的,ClassA默认调用了本身的Display1函数,可是Visual Studio有一个警告:
Warning: '
InheritanceAndPolymorphism.ClassA.Display1()
' hides inherited member 'InheritanceAndPolymorphism.ClassB.Display1()
'. Use thenew
keyword if hiding was intended.
C#中对方法的调用首先是查询ClassA本身中有无Display1函数,再查询其基类有无Display1函数。在基类和子类出现一样函数的状况现实项目中是存在的,多是基类代码过于陈旧了,子类既想用同签名的函数,又没法中止基类的同签名函数,故会出现这样的警告---尽管逻辑正确,可是这种设计仍是有一些瑕疵的。
咱们再试试在CalssA中经过base调用基类同名方法的状况:
ClassA: class ClassA:ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display1(); } } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
执行结果以下:
ClassA Display1
ClassB Display1
这个实验说明C#提供了base关键词,用于在继承中子类调用基类的函数或者变量(非private类型)。
一样的,在ClassA.Display1中调用其基类的Display2也是能够的,代码以下所示:
/// <summary> /// ClassB: acting as base class /// </summary> class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } } /// <summary> /// ClassA: acting as derived class /// </summary> class ClassA : ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display2(); } } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); Console.ReadKey(); } }
执行结果以下:
ClassA Display1
ClassB Display2
那么能否经过基类调用其子类的函数呢?
/// <summary> /// ClassB: acting as base class /// </summary> class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } } /// <summary> /// ClassA: acting as derived class /// </summary> class ClassA : ClassB { public void Display2() { Console.WriteLine("ClassA Display2"); } } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> class Program { static void Main(string[] args) { ClassB b = new ClassB(); b.Display2(); Console.ReadKey(); } }
运行报错:
Error: '
InheritanceAndPolymorphism.ClassB
' does not contain a definition for 'Display2
' and no extension method 'Display2
' accepting a first argument of type 'InheritanceAndPolymorphism.ClassB
' could be found
缘由是继承没法实现逆向调用,既基类没法调用子类。
除了构造函数和析构函数,子类继承了其基类的一些(包括private的成员变量和成员函数,只是没法访问)。
在C#中,一个类默认继承的是object类型,object是C#全部引用类型的基类;同时,继承具备传递性,如ClassC继承自ClassB,ClassB继承自ClassA,则ClassC可彻底复用ClassA的数据和函数---ClassC继承了ClassA。
C#中全部的类型均可被继承吗?
public class ClassW : System.ValueType { } public class ClassX : System.Enum { } public class ClassY : System.Delegate { } public class ClassZ : System.Array { }
执行结果:
'InheritanceAndPolymorphism.ClassW' cannot derive from special class 'System.ValueType'
'InheritanceAndPolymorphism.ClassX' cannot derive from special class 'System.Enum'
'InheritanceAndPolymorphism.ClassY' cannot derive from special class 'System.Delegate'
'InheritanceAndPolymorphism.ClassZ' cannot derive from special class 'System.Array'
运行的结果让人抓狂
在C#中,自定义类没法继承自C#内置的一些类,如System.ValueType
, System.Enum
, System.Delegate
, System.Array
, etc。
下面这个例子咱们再看看C++中的多类继承是否可在C#中实现:
public class ClassW { } public class ClassX { } public class ClassY : ClassW, ClassX { }
执行结果:
Compile time Error: Class '
InheritanceAndPolymorphism.ClassY
' cannot have multiple base classes: 'InheritanceAndPolymorphism.ClassW
' and 'ClassX
'.
执行结论是:C#仅支持单类继承,不支持C++的这种星型继承关系。 要使用星型继承关系,请用接口实现。
那么能否实现循环依赖继承呢?
public class ClassW: ClassY { } public class ClassX: ClassW { } public class ClassY : ClassX { }
代码逻辑很简单,ClassW继承自ClassY,ClassX继承自ClassW, ClassY继承自ClassX。
可是编译后报错了:
Error: Circular base class dependency involving '
InheritanceAndPolymorphism.ClassX
' and 'InheritanceAndPolymorphism.ClassW
'.
咱们得出一个结论,C#中不准环形依赖继承。
实例对象的是否可赋值
ClassB: public class ClassB { public int b = 100; } ClassA: public class ClassA { public int a = 100; }
Program.cs 代码以下
public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
咱们尝试判断ClassA、ClassB的对象是否可赋值。
编译的结果是:报错了
Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA' Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
尽管ClassA和ClassB里面的数据成员变量a数据一致,都为100,可是这里用等号比较的是类型--引用地址,故没法进行赋值。
咱们再来试试继承关系的:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
ClassA继承自ClassB,咱们但愿能够直接赋值其实例对象。
运行结果以下:
Error: Cannot implicitly convert type '
InheritanceAndPolymorphism.ClassB
' to 'InheritanceAndPolymorphism.ClassA
'.
运行结论:C#中子类对象可直接赋值给基类对象,基类对象须要往下强转。代码修改以下:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classB=classA; classA = (ClassA)classB; } }
这样编译就经过了。
若是ClassA不继承自ClassB,则这种强转在C#中是会报错的:
Cannot convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
Cannot convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'
System.ValueType
, System.Enum
, System.Delegate
, System.Array
, etc.
译文地址:http://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Polymorphism-and-Inheritance-Part.html
原文地址:Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)