2、抽象類
抽象類的特點:
1)、抽象類中的抽象成員必須標記為abstract,並且不能有任何實現。
方法不能有任何實現是指,方法沒有大括號,也沒有方法體。
只有大括號,沒有方法體的方法叫做空實現。
2)、抽象成員必須標記在抽象類中
3)、抽象類是有構造函數的,但抽象類不能被實例化
4)、子類繼承抽象類后,必須把父類中的所有抽象成員都重寫。(除非子類也是一個抽象類,則可以不重寫)
注意:在重寫抽象成員的時候,必須在前面加上override標記,否則編譯器會報錯。用虛方法實現多態的話,也要加上override標記,但省略override,編譯器不會報錯。
5)、抽象成員的訪問修飾符不能是private
6)、在抽象類中可以包含實例成員,並且它們可以不被子類實現
7)、如果父類的抽象方法中有參數。那么,繼承這個抽象父類的子類在重寫父類的方法的時候,必須傳入對應的的參數。
如果抽象父類的抽象方法中有返回值,那么子類在重寫這個抽象方法的時候,也必須要寫上返回值。
也就是說,子類在重寫抽象父類的抽象方法的時候,必須保證方法的簽名與父類的方法簽名一致。(方法的簽名:方法的參數和返回值)
什么時候使用抽象類:在已有的幾個類中,如果說我們可以抽象出一個父類,並且父類中必須寫上這幾個子類共有的一個方法,且不知道如何去寫這個方法。
圓形和矩形都有一個共同的父類:形狀,但形狀卻是抽象的,我們無法計算它的面積和周長,所以必須寫成抽象類。而圓形和矩形,它們計算面積和周長的方法也是不同的。這樣,我們就必須對形狀這個抽象類中,計算面積和周長的方法進行重寫。
class Program { static void Main(string[] args) { //使用多態求矩形的面積和周長以及圓形的面積和周長
Shape shape = new Square(5, 6); //new Circle(5);
double area = shape.GetArea(); double perimeter = shape.GetPerimeter(); Console.WriteLine("這個形狀的面積是{0},周長是{1}", area, perimeter); Console.ReadKey(); } } 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; } }
抽象類也可以包含抽象的屬性,因為屬性的本質是 get、set這兩個方法。
class Program { static void Main(string[] args) { //狗狗會叫 貓咪會叫
Animal a = new Cat();//new Dog();
a.Bark(); Console.ReadKey(); } } public abstract class Animal { public Animal(int age) { this.Age = age; } public virtual void T() { Console.WriteLine("動物有聲明"); } private int _age; public int Age { get { return _age; } set { _age = value; } } //Bark()沒有任何實現
public abstract void Bark(); public abstract string Name { get; set; } //Test()只有大括號,沒有方法體,是空實現
public void Test() { //空實現
} } public class Dog : Animal { public override void Bark() { Console.WriteLine("狗狗旺旺的叫"); } public override string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } } public class Cat : Animal { public override void Bark() { Console.WriteLine("貓咪喵喵的叫"); } public override string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } }
關於抽象類需要注意的幾點:
1)需要用abstract關鍵字標記
2)抽象方法不能有任何方法實現
3)抽象成員必須包含在抽象類中
4)由於抽象成員沒有任何實現,所以子類必須將抽象成員重寫(以override來標記)。
5)抽象類不能被實例化
6)抽象類的作用:為了讓子類繼承
7)抽象方法不能用static修飾
因為:抽象方法是沒有任何方法實現的,如果直接通過類名來調用,這樣的方法無法執行,沒有任何意義;
能調用抽象方法的只能是重寫了抽象方法的子類的對象(如果抽象類的子類也是抽象類的話,就無法調用)