什么是继承
继承的含义是:
-
允许一个类衍生出另一个现有类的功能。这个现有类称为基类或超类。
-
派生类/子类可以继承基类的属性和方法。
-
子类可以选择实现或覆写基类的某些方法。
-
子类新增自己的属性和方法。
继承的关键特征:
-
继承实现代码重用,子类不需要重写基类公共行为。
-
子类是基类的特例,拥有基类特征的子集。
-
继承体现了"是一个"的关系,比如狗是一个动物。
-
继承形成类的应用程序结构。
// 基类
class Animal {
public void eat() {...}
}
// 子类
class Dog extends Animal {
public void bark() {...}
}
为什么要继承
代码复用
子类可以直接继承父类公共的属性和行为,不需要重复编写共有代码,实现代码复用。
增强表现力
通过继承形成类的层次结构,更好地表现对象间的关系,如“一个行为”等。
功能扩展
子类可以选择重写父类的方法以扩展功能,实现特化。
逻辑清晰
继承能更清晰地划分pubic接口和实现细节,同时封装变化点。
符合面向对象思想
继承体现 OO 中“是一个”关系,比如Dog是一个Animal,更符合对象间的逻辑联系。
可读性好
继承层次关系清晰,易于理解不同类的联系和责任。
维护性强
修改父类的影响范围限定在继承体系中,降低变更维护成本。
兼容性强
功能扩展不会影响已有模块,独立开发子系统时尤其重要。
访问权修饰符
- public : 公开的
- private:私有的,只能在当前类的内部访问
- protected:受保护的,只能在当前类的内部以及该类的子类中访问。
- internal:只有在同一程序集中可访问,可以理解为只能在当前项目中访问。在同一个项目中,internal和public的权限是一样。
- protected internal
1. 能够修饰类的访问修饰符只有两个:public、internal,其他成员修饰符都可以修饰属性
2. 子类的访问权限不能高于父类的访问权限,会暴漏父类的成员。
// 在另外一个项目中可以访问Person
public class Person
{
}
// 在另外一个项目中无法访问Animal
internal class Animal
{
}
// 这样写错误,因为Dog子类拥有比父类Animal更高的权限
public class Dog:Animal{
}
new 的作用
创建对象实例
使用new可以创建类的实例对象,分配内存:
Cat cat = new Cat();
调用构造函数
new时会调用构造函数初始化对象:
public Cat()
{
//初始化代码
}
在继承中
子类使用new时会先调用父类参数构造函数,然后调用自身构造函数:
public class Cat : Animal
{
public Cat() : base()
{
//构造函数代码
}
}
重写虚方法
子类可以重写父类虚函数来修改行为:
public override void MakeSound()
{
//重写输出
}
类型转换
new可以实现向上、向下类型转换:
Animal a = new Cat();
Cat c = (Cat)a;
隐藏继承关系
子类构造函数可以主导初始化过程,修改继承行为。
里氏转换
- 子类可以赋值给父类
- 如果父类中装的是子类对象,那么可以将这个父类强转为子类对象。
//1.子类可以赋值给父类
Student s = new Student();
Person p = new Student(); //父类引用指向子类对象
//2.如果父类中装的是子类对象,那么可以将这个父类强转为子类对象。
// is:用于检查对象是否是指定类型或其派生类型的实例
if (p is Student)
{
Student ss = (Student)p;
ss.StudentSayHello();
}
else
{
Console.WriteLine("转换失败");
}
// as的用法
Student t = p as Student;
t.StudentSayHello();
Console.ReadKey();
// is和as区别
1. typeA is type B 仅判断,返回true/false
2. typeA as TypeB 先判断,再转换
如果成功了那就是真的成功了,如果不成功返回null