- 基本概念
- 面向对象的三个特性:继承、封装、多态
继承
- 继承的类型:单重继承、多重继承、多层继承(C#不支持类的多重继承,但允接口的多重继承)、接口继承
- 实现继承
//类
class child : MyBaseClass
class child : MyBaseClass,Interface1,Interface2
//接口(只能用于继承接口)
public struct childStruct : Interface
虚方法:把一个基类声明为virtual,就可以在任何派生类中重写该方法
public class Shape { public virtual void Draw() { WriteLine($"xxxxxxx"); } }
如果实现代码只有一行,可以用lambda运算符一起使用。
“`
public class Shape
{
public virtual void Draw() => WriteLine($”xxxxxxx”);
}C#在派生类重写函数时,要使用override关键字显示声明。
public class child : Shape { public override void Draw()=> WriteLine($"xxxxxxx"); }
成员字段和静态函数都不能声明为virtual,这个概念只有在类的实例函数才有意义
多态
- 使用多态性,可以动态的定义调用的方法,而不是在编译期间定义。编译器创建一个虚拟方法表(vtable),其中列出了可以在运行期间调用的方法,它根据运行期间的类型调用方法。
调用方法的基类版本
public class Shape { public virtual void Move(Position newPosition) { WriteLine($"xxxxxxx"); } } public class Rectangle : Shape { public override void Move(Position newPosition) { base.Move(newPosition);//调用了基类的方法 } }
抽象类和抽象方法:C#允许把类和方法声明为abstract。抽象类不能被实例化,而抽象方法不能直接实现,必须在非抽象的派生类中重写。显然,抽象方法本身也是虚拟的
public abstract class Shape { public abstract void Resize(int width,int height); } public class Ellipse : Shape { public override void Resize(int width,int height) { Size.Width=width; Size.Height=heigth; } }
使用抽象类Shape类和派生的Ellipse类,可以声明Shape的一个变量,但不能实例化。
Shape s1=new Ellipse();
DrawShape(s1);
密封类和密封方法:给类添加sealed修饰符,就不允许创建该类的子类
sealed class FinalClass { public sealed override void FinalMethod() { WriteLine($"xxxxxxx"); } }
之后再也不能扩展扩展这个方法的虚拟表
派生类的构造函数
public class Shape { public Shape() { Position=new Position(); Size =new Size(); } } public class Ellipse : Shape { public Ellipse() : base()//“继承”基类的构造方法 {} }
修饰符
- 访问修饰符:
修饰符 应用于 说明 public 所有类型和成员 任何代码均可以访问该项 protect 类型和内嵌类型的所有成员 只有派生的类型才能访问该项 internal 所有类型和成员 只能在包含它的程序集中访问该项 private 类型和内嵌类型的所有成员 只能在它的所属类型中访问该项 protected internal 类型和内嵌类型的所有成员 只能在包含它的程序集和派生类型的任何代码中访问该项 注意:internal是一个物理访问修饰符,其边界是一个程序集。其他是逻辑访问量
- 其他修饰符
修饰符 应用于 说明 new 函数成员 成员用相同的签名隐藏继承的成员 static 所有成员 成员不作用于类的具体事例,也称为类成员,而不是实例成员 virtual 仅函数成员 成员可以由派生类重写 abstract 仅函数成员 虚拟成员定义了成员的签名,但没有提供实现代码 override 仅函数成员 成员重写继承的虚拟或抽象成员 sealed 类、方法和属性 对于类,不能继承自密封类。对于属性和方法,成员重写已继承的虚拟成员,但任何派生类和派生成员都不能重写该成员。该修饰符必须与override一起使用 extern 仅静态[DllImport]方法 成员在外部用另一种语言实现。(参见第五章) 接口
public interface IBankAccount { void PayIn(); bool Withdraw() } public class SaveAccount : IBankAccount { void PayIn() => WriteLine($"xxxxxxx"); bool writedraw() => return true; }
编程的好习惯:通常用I开头表示接口
派生的接口:与类的派生类似。
is 和 as 运算符
as
Object o; IbankAccount account=(IBankAccount)o;
as的原理类似于类层次中的cast运算符——他返回对象的引用。如果对象不是所要求的类型,那么便返回空。(避免了类型转换)
IBankAccount account = o as IBankAccount if(account != null) { //operation }
is
Object o; if(o is IBankAccount) { //operate }