1. 类继承
可以使用一个已经存在的类做为基类-Base class.新类为派生类-derivedclass.
Class DerivedClasss : BaseClass
{ ……}
派生类扩展基类,因为它包含了基类成员。
派生类不能删除它所继承的任何成员。
2. 访问继承的成员
测试派生类使用基类成员。
class myBaseClass //基类
{
public string Field1 = "Base class field";
public void Method1(string value)
{
Console.WriteLine($"Base class --Method1:{value}");
}
}
class myDerivedClass:myBaseClass // 派生类
{
public string Field2 = "Derived class field";
public void Method2(string value)
{
Console.WriteLine($"Derived class -Method2:{value}");
}
}
测试代码:
class Program
{
static void Main(string[] args)
{
myDerivedClass myCls = new myDerivedClass();
myCls.Method1(myCls.Field1);//基类字段为参数的基类方法
myCls.Method1(myCls.Field2);//派生类字段为参数的基类方法
myCls.Method2(myCls.Field1);//基类字段为参数的派生类方法
myCls.Method2(myCls.Field2);//派生类字段为参数的派生类方法
}
}
输出:
Base class --Method1:Base class field
Base class --Method1:Derived class field
Derived class -Method2:Base class field
Derived class -Method2:Derived class field
3. 所有的类都派生自Object
类Object是唯一的非派生类,因为它是继承层次结构的基础。
单继承:一次只能继承自一个基类
继承的层次没有限制,意思是基类可以派生自另外一个类。
D <= C <=B <=A <=Object
子类D继承父类C,类C又是B类的子类,B类又是A类的子类,A类继承自Object类
4. 屏蔽基类的成员
派生类不能删除它继承的任何成员,但是可以使用与成员名称相同的成员来屏蔽基类成员。
要屏蔽一个继承数据成功,需要声明一个新的相同类型的同名成员即可。不包含返回类型的。
使用new 修饰符,告诉编译是故意屏蔽继承的成员的。否则编译器会警告你隐藏了一个继承成员。
修改上测试派生类:
class myDerivedClass:myBaseClass // 派生类
{
public string Field2 = "Derived class field";
new public string Field1 = "Derived class field";
public void Method2(string value)
{
Console.WriteLine($"Derived class -Method2:{value}");
}
new public void Method1(string value) //屏蔽基类成员函数
{
Console.WriteLine($"Derived class -Method2:{value}");
}
}
5. 访问基类
使用基类访问 base access 表达式访问隐藏的继承成员。关键字base后跟一个点,在加上成员名称组成
在派生类增加打印字段的方法:
public void PrintField()
{
Console.WriteLine($"Deriverd Field:{ Field1}");
Console.WriteLine($"Base Field:{base.Field1}");
}
测试:
class Program
{
static void Main(string[] args)
{
myDerivedClass myCls = new myDerivedClass();
myCls.PrintField();
}
}
输出:
Deriverd Field:Derived class field
Base Field:Base class field
6. 使用基类的引用
派生类的实例由基类的实例加上派生类新增的成员组成。派生类的引用指向整个类对象,包括基类部分。
class MyBaseClass //基类
{
public void Print()
{
Console.WriteLine("This is the base class");
}
}
class MyDerivedClass:MyBaseClass //派生类
{
new public void Print()
{
Console.WriteLine("This is the derived class");
}
}
测试:
class Program
{
static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass Mybase = (MyBaseClass)derived;//转换成基类
derived.Print();//从派生类部分调用Print
Mybase.Print();// 从基类部分调用Print
}
}
输出:
This is the derived class
This is the base class
虚方法和重载方法
虚方法可以使基类的引用访问”升至“派生类内。
可以使用基类引用调用派生类的方法:
派生类的方法和基类的方法有相同的签名和返回类型。
基类的方法使用virtual 标注。
派生类的方法使用override标注
在基类中方法被标记为virtual,在派生类中使用override标记该方法,重载基类的方法。
class MyBaseClass
{
virtual public void Print()
{
Console.WriteLine("This is a base method");
}
}
class MyDerivedClass:MyBaseClass
{
public override void Print()
{
Console.WriteLine("This is a Derived Class");
}
}
测试:
class Program
{
static void Main(string[] args)
{
MyDerivedClass derived = new MyDerivedClass();
MyBaseClass myBase = (MyBaseClass)derived;
derived.Print();
myBase.Print();
}
}
输出:
This is a Derived Class
This is a Derived Class
重载和被重载的方法必须有相同的可访问性。不能重载静态的方法或非虚方法。
方法,属性,索引器,事件都可以被声明为virtual和override的。
重载标记为override的方法
重载方法可以在继承的任何层次出现。
class MyDerivedClass2 : MyDerivedClass
{
public override void Print()
{
Console.WriteLine("This is the second derived class");
}
}
测试:
class Program
{
static void Main(string[] args)
{
MyDerivedClass2 derived = new MyDerivedClass2();
MyBaseClass myBase = (MyBaseClass)derived;
derived.Print();
myBase.Print();
}
}
输出:
This is the second derived class
This is the second derived class
结论:无论Print是通过派生类调用还是通过基类调用,都会调用最高派生类中的方法。
使用new 声明Print
将子类的派生类中的方法声明为new,则输出和上情况不同。
class MyDerivedClass2 : MyDerivedClass
{
public new void Print()
{
Console.WriteLine("This is the second derived class");
}
}
测试:
class Program
{
static void Main(string[] args)
{
MyDerivedClass2 derived = new MyDerivedClass2();
MyBaseClass myBase = (MyBaseClass)derived;
derived.Print();
myBase.Print();
}
}
输出:
This is the second derived class
This is a Derived Class
派生类使用new 覆盖基类的方法,通过派生类的实例调用时,使用派生列的方法,使用基类的引用调用时,方法调用只向上传递了一级,使用第一级的子类方法。
覆盖其它成员类型
在基类中定义一个属性:
private int _count = 5;
virtual public int Count
{
get { return _count; }
}
在派生类中:
private int _count = 10;
public override int Count => _count;
测试:
派生的Count 属性和基类引用的Count属性都输出10