类、继承、接口
1.类
-
匿名对象
var objUser = new {Name="Lilei",Age=18 }; //此时可直接读取匿名类属性 Console.WriteLine("Name:" + objUser.Name);// Name:Lilei //通过反射的方式获取属性值 static object GetObj() { var obj = new { Name = "Lilei", Age = 18 }; return obj; } static void Main(string[] args) { var obj = GetObj(); //此时可通过反射的方式获取属性值 string objName = obj.GetType().GetProperty("Name").GetValue(obj).ToString(); Console.WriteLine(objName);// Lilei }
2.继承
-
protected 关键字
访问仅限于包含类或从包含类派生的类型。但并不是说在子类中就可以随心所欲访问父类中的变量。只有访问是通过子类发生时,父类中的protected变量才能被访问。
class A { protected int a = 10; } class B :A{ public int b = 20; public void PrintOut() { var b1 = new B(); 1.正确 Console.WriteLine(b1.a);//正确使用方式 } } class B :A{ public int b = 20; public void PrintOut() { 2.正确 Console.WriteLine(a); } } class Program { static void Main(string[] args) { var b = new B(); b.PrintOut(); 3.错误 --- Console.WriteLine(b.a);//报错:A.a不可访问,因为它有一定的保护级别 } } class B :A{ public int b = 20; 4.错误 A a1 = new A(); public void PrintOut() { var b1 = new B(); Console.WriteLine(a1.a);//报错:无法通过"A"类型的限定符访问受保护的成员A.a,限定符必须是“B”类型(或从该类型派生) } }
-
转型,向上,向下
父类引用指向子类对象。
例一
Father f1 = new Son(); // 这就叫 upcasting (向上转型) // 现在 f1 引用指向一个Son对象 Son s1 = (Son)f1; // 这就叫 downcasting (向下转型) // 现在f1 还是指向 Son对象
例二
Father f2 = new Father(); Son s2 = (Son)f2; // 出错,子类引用不能指向父类对象
f1 指向一个子类对象,Father f1 = new Son(); 子类 s1 引用可以指向子类对象。而 f2 被传给了一个 Father 对象,Father f2 = new Father(); 子类 s2 引用不能指向父类对象。
public class Animal { public void eat() { Console.WriteLine("animal eating..."); } } class Bird : Animal { public void eat() { Console.WriteLine("bird eating..."); } public void fly() { Console.WriteLine("bird flying..."); } } class Program { public static void doEat(Animal h) { h.eat(); } static void Main(string[] args) { Animal b = new Bird(); //向上转型 b.eat(); //! error: b.fly(); b虽指向子类对象,但此时丢失fly()方法 Animal c1 = new Animal(); Bird c2 = new Bird(); doEat(c1); doEat(c2);//此处参数存在向上转型 } }
Animal b=new Bird(); //向上转型
b.eat();
此处将调用子类的 eat() 方法。原因:b 实际指向的是 Bird 子类,故调用时会调用子类本身的方法。
需要注意的是向上转型时 b 会遗失除与父类对象共有的其他方法。如本例中的 fly 方法不再为 b 所有。
public static void doEat(Animal h) { h.sleep(); }
这里以父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。不然的话,如果 doEat 以子类对象为参数,则有多少个子类就需要写多少个函数。这也体现了抽象编程思想。
3.抽象类和接口
1.
抽象类
表示的是,这个对象是什么
。接口
表示的是,这个对象能做什么。
2.一个类只能
继承一个类
(抽象类),但是可以实现多个接口
。3.
接口
更多的是在系统架构设计
方法发挥作用,主要用于定义模块之间的通信契约
。而抽象类
在代码实现
方面发挥作用,可以实现代码的重用
-
抽象类
(1)
抽象方法只作声明,而不包含实现
,可以看成是没有实现体的虚方法(2)
抽象类不能被实例化
(3) 抽象类可以但不是必须有抽象属性和抽象方法,但是
一旦有了抽象方>法,就一定要把这个类声明为抽象类
(4)
具体派生类必须覆盖基类的抽象方法
(5)
抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。
如果不覆盖,则其具体派生类必须覆盖它们。 -
接口
(1) 接口
不能被实例化
(2) 接口
只能包含方法声明
(3) 接口的成员
包括方法、属性、索引器、事件
(4) 接口中
不能包含常量、字段(域)、构造函数、析构函数、静态成员。
(5) 接口中的所有成员
默认为public
,因此接口中不能有private修饰符(6)
派生类必须实现接口的所有成员
(7) 一个类
可以直接实现多个接口
,接口之间用逗号隔开(8)
一个接口可以有多个父接口,实现该接口的类必须实现所有父接口中的所有成员
-
对比
1.相同点:
(1)
都可以被继承
(2) 都
不能被实例化
(3) 都
可以包含方法声明
(4)
派生类必须实现未实现的方法
区 别:
(1)
抽象基类
可以定义字段、属性、方法实现。接口
只能定义属性、索引器、事件、和方法声明,不能包含字段。(2)
抽象类
是一个不完整的类
,需要进一步细化,而接口
是一个行为规范
。证明其是表述一类“我能做。。。”(3)
接口
可以被多重实现
,抽象类
只能被单一继承
(4)
抽象类
更多的是定义在一系列紧密相关
的类间,而接口
大多数是关系疏松但都实现某一功能的类
中(5)
抽象类
是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性
;接口
是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性
(6)
接口
基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
(7)
接口
可以用于支持回调
,而继承并不具备这个特点(8)
抽象类实现的具体方法默认为虚的
,但实现接口的类中的接口方法却默认为非虚的
,当然您也可以声明为虚的(9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法
接口
基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
(7)
接口
可以用于支持回调
,而继承并不具备这个特点(8)
抽象类实现的具体方法默认为虚的
,但实现接口的类中的接口方法却默认为非虚的
,当然您也可以声明为虚的(9) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法