实现多态的方式——抽象类


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修饰  

    因为:抽象方法是没有任何方法实现的,如果直接通过类名来调用,这样的方法无法执行,没有任何意义;

       能调用抽象方法的只能是重写了抽象方法的子类的对象(如果抽象类的子类也是抽象类的话,就无法调用)

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM