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

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

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

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

 

posted @ 2015-10-16 21:00  苏打兴  阅读(4686)  评论(0编辑  收藏  举报