一、继承的概念
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的属性和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
二、继承的特点
1.派生类是对基类的扩展,派生类可以添加新的成员,但不能移除已经继承的成员的定义。
2.继承是可以传递的。如果 C 从 B 中派生,B 又从 A 中派生,那么 C 不仅继承了 B 中声明的成员,同样也继承了 A 中声明的成员。
3.构造函数和析构函数不能被继承,除此之外其他成员能被继承。基类中成员的访问方式只能决定派生类能否访问它们。
4.派生类如果定义了与继承而来的成员同名的新成员,那么就可以覆盖已继承的成员,但这并不是删除了这些成员,只是不能再访问这些成员。
5.类可以定义虚方法、虚属性及虚索引指示器,它的派生类能够重载这些成员,从而使类可以展示出多态性。
6.派生类只能从一个类中继承,可以通过接口来实现多重继承。
三、继承的类型
1.单重继承:表示一个类可以派生自一个基类。C#就采用这种继承。
2.多重继承:多重继承允许一个类派生自多个类。C#不支持类的多重继承,但允许接口的多重继承。
3.多层继承:多层继承允许继承有更大的层次结构。类B派生自类A,类C又派生自类B。其中,类B也称为中间基类,C#支持它,也很常用。
4.接口继承:定义了接口的继承。这里允许多重继承。
四、继承的实现
派生自另一个类的一个类,语法如下:
class Useinheritance1 : Useinheritance2
{
}
class Useinheritance2
{
}
对于结构,语法如下(只能用于接口继承):
struct Useinheritance1 : IInterfacel
{
}
interface IInterfacel
{
}
五、子类重写父类的成员方法
虚方法(virtual):如果基类中某个方法,想让派生类去重写那么基类就在该方法的返回值前面加上virtual关键字。
重写(override):如果派生类打算重写该方法,那么就在方法的返回值前面加上override关键字。
class Program
{
static void Main(string[] args)
{
new Useinheritance1().GetInfo();
new Useinheritance2().GetInfo();
}
}
class Useinheritance1 : Useinheritance2
{
public override void GetInfo()
{
Console.WriteLine("我是派生类中的方法!");
}
}
class Useinheritance2
{
public virtual void GetInfo()
{
Console.WriteLine("我是父类中的方法!");
}
}
运行结果如下:
六、抽象类和抽象方法
C#允许把类和方法声明为abstract。
1.抽象类不能实例化。
2.抽象方法不能直接实现,必须在非抽象的派生类中重写。显然,抽象方法本身也是虚拟的。
3.如果类包含抽象方法,则该类也是抽象的,也必须声明为抽象的。
class Program
{
static void Main(string[] args)
{
new Useinheritance1().GetInfo();
}
}
class Useinheritance1 : Useinheritance2
{
public override void GetInfo()
{
Console.WriteLine("我是派生类中的方法!");
}
}
public abstract class Useinheritance2
{
public abstract void GetInfo();
}
运行结果如下:
七、接口的继承
接口可以彼此继承,其方式与类的继承方式相同,下面定义一个了Iinterface1接口,派生自接口Iinterface2,类Useinheritance1继承Iinterface1接口就需要实现两个接口中定义的所有方法。
class Program
{
static void Main(string[] args)
{
new Useinheritance1().GetInfo1();
new Useinheritance1().GetInfo2();
}
}
public class Useinheritance1 : Iinterface1
{
public virtual void GetInfo1()
{
Console.WriteLine("我是派生接口中的方法!");
}
public virtual void GetInfo2()
{
Console.WriteLine("我是父接口中的方法!");
}
}
interface Iinterface1 : Iinterface2
{
public void GetInfo1();
}
interface Iinterface2
{
public void GetInfo2();
}
运行结果如下:
八、密封类
如果不应创建派生自某个自定义类的类,该自定义类就应密封。给类添加sealed修饰符,就不允许创建该类的子类。
public sealed class Useinheritance1
{
public void GetInfo()
{
}
}
九、base的使用
在继承的关系中,子类如果需要调用父类中的成员可以借助 base 关键字来完成。
class Program
{
static void Main(string[] args)
{
new Useinheritance1().GetInfo();
}
}
public class Useinheritance1 : Useinheritance2
{
public override void GetInfo()
{
Console.WriteLine("我是派生类中的方法!");
base.GetInfo();
}
}
public class Useinheritance2
{
public virtual void GetInfo()
{
Console.WriteLine("我是父类中的方法!");
}
}
运行结果如下:
十、转换运算符
as运算符
as 运算符用于在可兼容的引用类型之间执行类似于强制类型转换的操作。
如果不能转换,则值为null。
与强制类型转换的差别:
1.as只能针对引用型变量。
2.如果不能转换,as运算不会引起异常,只是值为null。
class Program
{
static void Main(string[] args)
{
object obj = "类型转换成功!";
string str = obj as string;
if (str != null)
{
Console.WriteLine(obj.ToString());
}
else
{
Console.WriteLine("转换类型失败!");
}
}
}
运行结果如下:
is运算符
判断一个对象是否能某个类(及子类)的实例。
class Program
{
static void Main(string[] args)
{
object obj = "类型转换成功!";
if(obj is string)
{
Console.WriteLine(obj.ToString());
}
else
{
Console.WriteLine("转换类型失败!");
}
}
}
运行结果如下: