允许无需重新改写现有类,重用现有类(基类,亦称超类、父类)去创建新类(子类,亦称派生类)
C#所有类继承于Object类

多态性
对象可以表示多个类型的能力,以自己的方式响应同一消息
一个类型派生于一个基类型,派生类具有基类的所有非私有(非private)数据和行为
派生类型的每个方法采用基类型的实现代码,除非在派生类型的定义中指定重写该方法的实现代码
一般用于增加现有类型的功能,或许多相关的类型共享一组重要的公共功能的场合
一个类型实现若干接口,接口仅包含方法的签名,不继承任何实现代码
一般用于指定该类型具有某类可用的特性,在接口中定义通用的实现代码是没有意义的
接口即契约,类型派生于接口,即保证该类提供该接口规定的功能
[类修饰符] class 类名 [: 基类] {类体;}
class Point //等同于:class Point : Object
{
int x, y;
}
class ColoredPoint : Point //派生类,从Point派生
{
int color;
}
class Colored3dPoint : ColoredPoint//派生类,从ColoredPoint派生
{
int z;
}
用于从派生类中访问基类的成员
base(参数):指定创建派生类实例时应调用的基类构造函数
base.方法(参数):调用基类上已被其他方法重写的方法
base.字段名:访问基类的数据成员
不能从静态方法中使用 base 关键字
只能在实例构造函数、实例方法或实例访问器中使用
public class Person
//等同于:class Person : Object
{
public String name; public int age;
public Person(String name, int age)
//基类构造函数
{
this.name = name; this.age = age;
}
public void print() //基类的实例方法
{
Console.Write("name={0},age={1}", this.name, this.age);
}
}
public class Student : Person //派生类
{
public String studentID;
public Student(String name, int age, String id)
: base(name, age)
//派生类构造函数,使用base调用基类构造函数
{
this.studentID = id;
}
public new void print()
{
base.print();
//使用base调用基类的方法
Console.WriteLine(",studentID={0}", this.studentID);
}
}
构造函数不能被继承,也不能被覆盖,名称必须与类名相同
通过关键字new创建对象实例时,会根据传入的参数调用相匹配的构造函数
调用构造函数前,需要先调用其基类的构造函数
通过继承,派生类继承基类中除构造函数之外的所有成员
与基类成员的访问修饰符无关
如果在派生类中声明了与继承的成员同名的成员,则该重名成员将隐藏从基类继承的同名成员变量
class Parent // 基类Parent
{
public String name;
public String sex;
}
class Child : Parent // 派生类Child
{
public String name;
// 成员变量,隐藏从基类继承的同名成员变量name
public Child(String name, String sex) // 构造函数
{
this.name = name;
//this.name引用Child声明的成员变量
this.sex = sex;
//this.sex引用从Parent继承的成员变量
base.name = name + "'s parent";
//base.name引用从基类Parent继承的同名成员变量name
}
public void print()
{
Console.WriteLine(this.name + " " + this.sex + " " + base.name);
}
}
虚方法
在基类中,使用virtual关键字声明的方法
隐藏方法
在派生类中,使用new关键字声明的与基类中相同签名的方法
派生类中相同签名方法重新定义了基类中的方法,即隐藏了基类中的同名方法
重写方法
在派生类中,使用关键字override声明的与基类中相同签名的方法

将关键字 abstract 置于关键字 class 的前面可以将类声明为抽象类
抽象类不能实例化(不能用new),一般用于提供多个派生类可共享的基类的公共定义
可以定义抽象类型的变量,但其值必须为 null,或者是其派生的非抽象类的实例的引用
允许(但不要求)抽象类包含抽象成员
抽象类不能被密封
当从抽象类派生非抽象类时,这些非抽象类必须实现所继承的所有抽象成员,从而重写那些抽象成员
抽象类中通过将关键字 abstract 添加到实例方法的返回类型的前面可以定义抽象方法
abstract class Animal
// 基类Animal:抽象类
{
public String name;
public abstract void SayHi();
public Animal(String name)
{ this.name = name; } //构造函数
}
class Dog : Animal // 派生类Dog
{ //重写SayHi()
public override void SayHi() { Console.WriteLine(this.name + " Wow Wow!"); }
public Dog(String name) : base(name) { }
//构造函数
}
class Cat : Animal // 派生类Cat
{ //重写SayHi()
public override void SayHi() { Console.WriteLine(this.name + " Mew Mew!"); }
public Cat(String name) : base(name) { } //构造函数
}
//class Horse : Animal { } //编译错误,非抽象类Horse继承了抽象类Animal,但未实现抽象方法
abstract class Fish : Animal //编译OK,抽象类Fish继承了抽象类Animal,但未实现抽象方法
{
public Fish(String name) : base(name) { }
}
通过将关键字 sealed 置于关键字 class 的前面,可以将类声明为密封类
接口定义协定

接口可由类和结构实现
[类修饰符] class 类名:基接口列表
{
类体;
}
接口分部与继承
public interface IDimensions //基类:接口IDimensions
{
float getLength(); float getWidth();
}
public class Box : IDimensions //派生类Box
{
float length; float width;
Box(float length, float width)
{
this.length = length; this.width = width;
}
public float getLength() { return length;}
public float getWidth() { return width; }
}
派生类对象可以表示多个类型的能力
类方法多态性的实现有两种方式:方法重载和方法重写
在这里插入图片描述
class P0 // 基类
{
public void MethodA(){Console.WriteLine("调用类P0的方法methodA()");}
}
class C0 : P0 // 派生类
{
public void MethodA(String str1) //重载方法:重载从基类继承的MethodA()
{
Console.WriteLine("调用类C0的方法MethodA():" + str1);
}
public void MethodB(String str1) //重载方法:重载MethodB(int a)
{
Console.WriteLine("调用C0类的实例方法MethodB(String str1):" + str1);
}
public void MethodB(int a) // 重载方法:重载MethodB(String str1)
{
Console.WriteLine("调用C0类的实例方法MethodB(int a):" + a);
}
}
class A0 // 基类
{
public virtual void MethodA()
{
Console.WriteLine("调用A0的类的实例方法MethodA()");
}
}
class A01 : A0 // 派生类
{
public override void MethodA()//重写方法:重写从基类A0继承的方法
{
Console.WriteLine("调用A01的类的实例方法MethodA()");
}
}
class A02 : A0 // 派生类
{
public override void MethodA()//重写方法:重写从基类A0继承的方法
{
Console.WriteLine("调用A02的类的实例方法MethodA()");
}
}