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修饰
因为:抽象方法是没有任何方法实现的,如果直接通过类名来调用,这样的方法无法执行,没有任何意义;
能调用抽象方法的只能是重写了抽象方法的子类的对象(如果抽象类的子类也是抽象类的话,就无法调用)