继承和多态
继承、封装、多态是面向对象的三大特性。这里主要理解一下继承和多态。继承可以理解为子类继承父类。
其中有几个词在继承和多态中经常用到:new、virtual、override、sealed、abstract
结合例子看一下这几个词的用法和说明:
1、new:我认为就是一个标记。目的就是为了避免冲突。父类中的方法和子类中的方法一模一样,子类的方法前加:new,来避免冲突。
代码:
public class Parent { public Parent() { Console.WriteLine("父类构造"); } public void GaGa() { Console.WriteLine("父类的【GaGa】叫方法"); } public virtual void Walk() { Console.WriteLine("父类走的动作"); } } public class Children : Parent { public Children() { Console.WriteLine("子类的构造"); } new public void GaGa() { Console.WriteLine("子类方法GaGa与父类未公开继承的GaGa方法重叠,子类用new将父类方法隐藏。"); } public override void Walk() { Console.WriteLine("子类走的动作"); } }
父类Parent中:
public void GaGa()
{
Console.WriteLine("父类的【GaGa】叫方法");
}
子类中同样有这样的方法:加入new方法
new public void GaGa()
{
Console.WriteLine("子类方法GaGa与父类未公开继承的GaGa方法重叠,子类用new将父类方法隐藏。");
}
那我们调用时这样写:
class Program { static void Main(string[] args) { Parent p = new Children(); //父类GaGa()方法 p.GaGa(); Console.WriteLine("---------------------------------------"); } }
因为有new的区分父类和子类的方法(完全相同的方法),所以调用的是父类的GaGa方法。
执行结果截图:
分析执行结果:子类继承父类,实例化子类时,先构造父类构造,再构造子类构造,之后我们调用了子类中与父类相同方法的GaGa(),但是我们用new在子类方法前加以区分。
二、virtual 虚方法,也是一个标记,标记这个类中的方法可以在子类中重写覆盖(override)或者隐藏(new)
1、override
public class Parent { public Parent() { Console.WriteLine("父类构造"); } public void GaGa() { Console.WriteLine("父类的【GaGa】叫方法"); } public virtual void Walk() { Console.WriteLine("父类走的动作"); } } public class Children : Parent { public Children() { Console.WriteLine("子类的构造"); } new public void GaGa() { Console.WriteLine("子类方法GaGa与父类未公开继承的GaGa方法重叠,子类用new将父类方法隐藏。"); } public override void Walk() { Console.WriteLine("子类走的动作,完全覆盖父类公开可以继承的此方法"); } }
这里除了注意父类和子类的walk()方法的写法,还需注意:
Parent p = new Children(); //父类GaGa()方法 p.GaGa(); ----------这个是子类用new方法加以区别父类的方法 p.Walk(); ----------这个是子类用 override 重写覆盖父类方法
注意运行结果:
我们实例化的是子类,但是赋给了父类引用,而子类中正好Walk()方法覆盖了父类方法。这样调用的时候就是子类的Walk()
方法的实现。
(2)new
public class Parent { public Parent() { Console.WriteLine("父类构造"); } public void GaGa() { Console.WriteLine("父类的【GaGa】叫方法"); } public virtual void Walk() { Console.WriteLine("父类走的动作"); } } public class Children : Parent { public Children() { Console.WriteLine("子类的构造"); } new public void GaGa() { Console.WriteLine("子类方法GaGa与父类未公开继承的GaGa方法重叠,子类用new将父类方法隐藏。"); } new public void Walk()-------------------------看这!!!!!!!!! { Console.WriteLine("子类走的动作,完全覆盖父类公开可以继承的此方法"); } }
区别于上面,父类Walk()标记为virtual 可以重写,现在的子类是用new也是区别于相同方法
调用结果:
对的,子类没有用override覆盖父类方法,所以调用的还是父类的那个自己的Walk()方法。
三、override:上面已经提到是在父类中用到virtual,子类就用override进行重写。
四、sealed密封的,密封类是不可以继承的。
五、abstract:抽象,抽象类中的抽象方法,继承了此类的子类必须重写抽象实现
总结:
关键字 | 可以拥有此关键字的对象 | 作用 | ||
new | 子类与父类拥有相同方法的子类方法 | 隐藏父类相同方法,这样子类和父类的方法相互独立,不会存在冲突 | ||
virtual | 父类的方法 | 父类的此方法可以让父类进行重写,子类可以根据实际情况决定是否重写。 | ||
override | 子类对应重写父类的方法,用此标记。 | 用于子类对父类标记virtual的方法的重写标记,这样就实实在在的覆盖了父类的那个可以允许子类重写的方法。记住是覆盖。 | ||
abstract | 用于类和方法 | 类--不可以实例化,方法--如果继承此类,就必须实现abstract方法。 | ||
sealed | 类 | 表示,该类不可以继承 |