用virtual修飾的方法叫做虛方法 虛方法可以在子類中通過override關鍵字來重寫 常見的虛方法:ToString() Equalsc#基礎多態的三種手段
多態的概念概念:讓一個對象能夠表現出多種的狀態(類型)
實現多態的3種手段:1、虛方法 2、抽象類 3、接口
關於虛方法需要注意的幾點:
1.父類中如果有方法需要讓子類重寫,則可以將該方法標記為virtual
2.虛方法在父類中必須有實現,哪怕是空實現。
3.虛方法子類可以重寫(override),也可以不重寫
關於抽象方法注意的幾點:
1.需要用abstract關鍵字標記
2.抽象方法不能有任何方法實現。
3.抽象成員必須包含在抽象類中。
4.由於抽象成員沒有任何實現,所以子類必須將抽象成員重寫。
5.抽象類不能實例化,
抽象類的作用:抽象類的作用就是為了讓子類繼承。
6.抽象類中可以包括抽象成員,可以包括有具體代碼的成員。
7. 還有抽象方法不能用static修飾
1.接口中只能包含方法(屬性、事件、索引器也都是方法)
2.接口中的成員都不能有任何實現。光說不做
3.接口不能被實例化。
4.接口中的成員不能有任何訪問修飾符。(默認為public)
5.實現接口的子類必須將接口中的所有成員全都實現。
6.子類實現接口的方法時,不需要任何關鍵字,直接實現即可。
7.接口存在的意義就是為了多態。
//1.虛方法
用virtual修飾的方法叫做虛方法
虛方法可以在子類中通過override關鍵字來重寫
常見的虛方法:ToString() Equals
//1)、虛方法
//步驟:
//1、將父類的方法標記為虛方法 ,使用關鍵字 virtual,這個函數可以被子類重新寫一個遍。
public class Employee { public virtual void DaKa() { Console.WriteLine("九點打卡"); } } public class Manager : Employee { public override void DaKa() { Console.WriteLine("經理11點打卡"); } } public class Programmer : Employee { public override void DaKa() { Console.WriteLine("程序猿不打卡"); } }
//抽象類1
//2)、抽象類
//當父類中的方法不知道如何去實現的時候,可以考慮將父類寫成抽象類,將方法寫成抽象方法。
抽象類與抽象方法由abstract修飾
abstract的使用注意
抽象方法沒有方法體
抽象成員只能存在於抽象類中
抽象類可以有非抽象成員
抽象類的派生類必須實現抽象方法體
抽象類只能用作基類,無法實例化
public abstract class Animal//抽象類 { public virtual void T() { Console.WriteLine("我是虛方法"); //如果父類中的方法有默認的實現,並且父類需要被實例化,這時可以考慮將父類定義成一個普通類,用虛方法來實現多態。 // 如果父類中的方法沒有默認實現,父類也不需要被實例化,則可以將該類定義為抽象類。 } //6.在抽象類中可以包含實例成員。 // 並且抽象類的實例成員可以不被子類實現 private int _age; public int Age { get { return _age; } set { _age = value; } } public Animal(int age) { this.Age = age; } public abstract void Bark();//抽象方法 1.抽象成員必須標記為abstract,並且不能有任何實現。 public abstract string Name//抽象屬性 { get; set;// //4. 抽象屬性 子類繼承抽象類后,必須把父類中的所有抽象成員都重寫。 } // public abstract string TestString(string name); //2.抽象成員必須在抽象類中。 //3.抽象類不能被實例化 public Animal() { } //public void Test() //{ // //空實現 //} } public abstract class Test : Animal { //(除非子類也是一個抽象類,則可以不重寫) } public class Dog : Animal//alt +shirt+F10 { // public abstract void Test(); public override void Bark() { Console.WriteLine("狗狗旺旺的叫"); } public override string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } //string //public override string TestString(string name) //{ // //throw new NotImplementedException(); //} //如果父類的抽象方法中有參數,那么。繼承這個抽象父類的子類在重寫父類的方法的時候必須傳入對應的參數。 //如果抽象父類的抽象方法中有返回值,那么子類在重寫這個抽象方法的時候 也必須要傳入返回值。 }
//抽象類2 public abstract class Shape { public abstract double GetArea(); public abstract double GetPerimeter(); } public abstract class Shape { public abstract double GetArea(); public abstract double GetPerimeter(); } public class Circle : Shape { private double _r; public double R { get { return _r; } set { _r = value; } } public Circle(double r) { this.R = r; } public override double GetArea() { return Math.PI * this.R * this.R; } public override double GetPerimeter() { return 2 * Math.PI * this.R; } } public class Square : Shape { private double _height; public double Height { get { return _height; } set { _height = value; } } private double _width; public double Width { get { return _width; } set { _width = value; } } public Square(double height, double width) { this.Height = height; this.Width = width; } public override double GetArea() { return this.Height * this.Width; } public override double GetPerimeter() { return (this.Height + this.Width) * 2; } }
1.抽象成員必須標記為abstract,並且不能有任何實現。
2.抽象成員必須在抽象類中。
3.抽象類不能被實例化
4.子類繼承抽象類后,必須把父類中的所有抽象成員都重寫。
(除非子類也是一個抽象類,則可以不重寫)
5.抽象成員的訪問修飾符不能是private
6.在抽象類中可以包含實例成員。
並且抽象類的實例成員可以不被子類實現
7.抽象類是有構造函數的。雖然不能被實例化。
8、如果父類的抽象方法中有參數,那么。繼承這個抽象父類的子類在重寫父類的方法的時候必須傳入對應的參數。
如果抽象父類的抽象方法中有返回值,那么子類在重寫這個抽象方法的時候 也必須要傳入返回值。
======
如果父類中的方法有默認的實現,並且父類需要被實例化,這時可以考慮將父類定義成一個普通類,用虛方法來實現多態。
如果父類中的方法沒有默認實現,父類也不需要被實例化,則可以將該類定義為抽象類。
接口
接口是一種規范。
只要一個類繼承了一個接口,這個類就必須實現這個接口中所有的成員為了多態。 接口不能被實例化。
也就是說,接口不能new(不能創建對象)
接口中的成員不能加“訪問修飾符”,接口中的成員訪問修飾符為public,不能修改。
(默認為public) 接口中的成員不能有任何實現(“光說不做”,只是定義了一組未實現的成員)。
接口中只能有方法、屬性、索引器、事件,不能有“字段”和構造函數。
接口與接口之間可以繼承,並且可以多繼承。
接口並不能去繼承一個類,而類可以繼承接口 (接口只能繼承於接口,而類既可以繼承接口,也可以繼承類)
實現接口的子類必須實現該接口的全部成員。
一個類可以同時繼承一個類並實現多個接口,如果一個子類同時繼承了父類A,並實現了接口IA,那么語法上A必須寫在IA的前面。
class MyClass:A,IA{},因為類是單繼承的。顯示實現接口的目的:解決方法的重名問題
什么時候顯示的去實現接口:
當繼承的借口中的方法和參數一摸一樣的時候,要是用顯示的實現接口
當一個抽象類實現接口的時候,需要子類去實現接口。
public interface IFlyable { //接口中的成員不允許添加訪問修飾符 ,默認就是public void Fly(); string Test(); //不允許寫具有方法體的函數 // string _name;//不能含字段 string Name { get;//自動屬性 set; } } //為了多態。 // 接口不能被實例化。 //也就是說,接口不能new(不能創建對象) IFlyable fly1 = new Bird(); //顯示實現接口就是為了解決方法的重名問題 IFlyable fly = new Bird(); IFlyable FLY1 = new Bird(); fly.Fly(); Bird bird = new Bird(); bird.Fly(); public class Bird : IFlyable { public void Fly() { Console.WriteLine("鳥飛會"); } /// <summary> /// 顯示實現接口 /// </summary> // void IFlyable.Fly() //{ // Console.WriteLine("我是接口的飛"); //} void IFlyable.Fly() { Console.Write("我是接口的飛"); } } public interface IFlyable { void Fly(); }