C#中的继承,C#是面向对象语言,面向对象三种特性:封装、继承、多态。
这里主要是继承,这篇只是基础
首先定义一个基类:积累中含有一个使用virtual定义的一个虚方法。 virtual关键字用于在基类中修饰方法。
一、virtual的使用会有两种情况:
1、在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。
2、在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。
二、virtual用虚方法标记:
a、可在派生类中以override覆盖此方法
b、不覆盖也可由对象调用
c、无此标记的方法(也无其他标记),重写时需用new隐藏原方法
实例:
class Program { static void Main(string[] args) { A a; // 定义一个a这个A类的对象.这个A就是a的申明类 A b; // 定义一个b这个A类的对象.这个A就是b的申明类 A c; // 定义一个c这个A类的对象.这个A就是b的申明类 A d; // 定义一个d这个A类的对象.这个A就是b的申明类 a = new A(); // 实例化a对象,A是a的实例类 b = new B(); // 实例化b对象,B是b的实例类 c = new C(); // 实例化b对象,C是b的实例类 d = new D(); // 实例化b对象,D是b的实例类 a.Func(); // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A b.Func(); // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B c.Func(); // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B d.Func(); // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A D d1 = new D(); d1.Func(); // 执行D类里的Func(),输出结果 Func In D Console.ReadLine(); } } class A { public virtual void Func() // 注意virtual,表明这是一个虚拟函数 { Console.WriteLine("Func In A"); } } class B : A // 注意B是从A类继承,所以A是父类,B是子类 { public override void Func() // 注意override ,表明重新实现了虚函数 { Console.WriteLine("Func In B"); } } class C : B // 注意C是从A类继承,所以B是父类,C是子类 { } class D : A // 注意B是从A类继承,所以A是父类,D是子类 { public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现 { Console.WriteLine("Func In D"); } }
三、重载和重写的区别:
重写:通常,派生类继承基类的方法。因此,在调用对象继承方法的时候,调用和执行的是基类的实现。但是,有时需要对派生类中的继承方法有不同的实现。例如,假设动物类存在“跑"的方法,从中派生出马和狗,马和狗的跑得形态是各不相同的,因此同样方法需要两种不同的实现,这就需要"重新编写"基类中的方法。"重写"基类方法就是修改它的实现或者说在派生类中重新编写。
重载:在一个类中用相同的名称但是不同的参数类型创建一个以上的过程、实例构造函数或属性。
// 这里是重载 class Program { static void Main(string[] args) { string s = null; show(s); object a = "123"; show(a); } static void show(string s) { Console.WriteLine("string"); } static void show(object o) { Console.WriteLine("object"); } } class tarce { public void setWidth(int w) { width = w; } public void setHeight(int h) { height = h; } protected int width; protected int height; // Virtual虚方法 public virtual string GetResult() { return "我是一个虚方法"; } }
定义一个派生类:继承了基类
class paisheng : tarce { public int getArea() { return (width * height); } // 在派生类中重写Virtual虚方法 public override string GetResult() { return "我是在派生类中重写的虚方法"; } }
调用以上两个类:
class Program { /* C#主要的运行函数,就是main函数 */ static void Main(string[] args) { paisheng pai = new paisheng(); pai.setWidth(12); pai.setHeight(9); int area = pai.getArea(); Console.WriteLine(area); string str = pai.GetResult(); Console.WriteLine(str); } }
这里再墨迹一下:
Private:私有变量,只能自己调用,你儿子只能是你儿子
Protected:受保护的变量,你大爷永远是你大爷,但他也可能是别人的大爷。
Public:公共变量,公共电话,谁都能打。
测试使用全部代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace @virtual { class Program { static void Main(string[] args) { paisheng pai = new paisheng(); pai.setWidth(12); pai.setHeight(9); int area = pai.getArea(); Console.WriteLine(area); string str = pai.GetResult(); Console.WriteLine(str); Console.WriteLine("======================================================================"); A a; // 定义一个a这个A类的对象.这个A就是a的申明类 A b; // 定义一个b这个A类的对象.这个A就是b的申明类 A c; // 定义一个c这个A类的对象.这个A就是b的申明类 A d; // 定义一个d这个A类的对象.这个A就是b的申明类 a = new A(); // 实例化a对象,A是a的实例类 b = new B(); // 实例化b对象,B是b的实例类 c = new C(); // 实例化b对象,C是b的实例类 d = new D(); // 实例化b对象,D是b的实例类 a.Func(); // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A b.Func(); // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B c.Func(); // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B d.Func(); // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A D d1 = new D(); d1.Func(); // 执行D类里的Func(),输出结果 Func In D Console.ReadLine(); } } // 这是基类 class tarce { public void setWidth(int w) { width = w; } public void setHeight(int h) { height = h; } protected int width; protected int height; // Virtual虚方法 public virtual string GetResult() { return "我是一个虚方法"; } } // 这是派生类 class paisheng : tarce { public int getArea() { return (width * height); } // 在派生类中重写Virtual虚方法 public override string GetResult() { return "我是在派生类中重写的虚方法"; } } class A { public virtual void Func() // 注意virtual,表明这是一个虚拟函数 { Console.WriteLine("Func In A"); } } class B : A // 注意B是从A类继承,所以A是父类,B是子类 { public override void Func() // 注意override ,表明重新实现了虚函数 { Console.WriteLine("Func In B"); } } class C : B // 注意C是从A类继承,所以B是父类,C是子类 { } class D : A // 注意B是从A类继承,所以A是父类,D是子类 { public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现 { Console.WriteLine("Func In D"); } } }