如果父类中的方法有默认的事项,并且父类要被实例化,这时考虑将父类定义成一个普通类考虑用虚方法实现多态
当父类中的方法没有默认的实现,也不需要实例化,这是可以将该类定义为抽象类
当父类的不知道怎么实现用抽象类关键字 abstract 抽象方法不写方法体,连{}也不写因为{}叫空方实现不叫没有方法体
抽象类不能实例化(因为调用不到)抽象类与虚方法的区别是虚方法里有实现而抽象类中没有实现
一、抽象类:
1、抽象成员必须记为abstract,访问修饰符必须写上public,因为在类中不写修饰符默认为private,并且不能有任何实现
2、抽象成员必须在抽象类中
3、抽象类不能被实例化,但是可以有构造函数
4、子类继承抽象类后,必须把父类中所有的抽象成员都重写(实现)除非子类是个抽象类则可以不必重写
5、在抽象类中可以包含实例成员并且抽象类中的实例成员可以不被子类实现
6、重写抽象类的方法签名必须和抽象类中的方法签名相同(即方法名返回值参数个数和参数类型)
7、抽象类中也可以有虚方法
抽象类中可以写抽象方法抽象属性非抽象方法,字段,无参的构造函数,非抽象成员可以继承给子类用
抽象成员必须在抽象类中,抽象类可以继承抽象类,如果子类也是抽象类那么可以不用重写父类中的成员
一旦有类继承了抽象类那么抽象类中的成员必须要全部实现
抽象类基本语法:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _01204抽象类 { class Program { static void Main(string[] args) { //狗狗旺旺叫 猫咪喵喵叫 //我们不知道父类将如何实现是把它写成抽象类知道的话就写成虚方法 //Animal an = new Animal();报错因为抽象类不能被实 Animal a = new Dog(); a.Bark(); Animal c = new Cat(); c.Bark(); Console.ReadKey(); } } public abstract class Animal { //抽象类中可以有实例成员 private int _age; public int Age { get { return _age; } set { _age = value; } } //抽象类可以有构造函数但不能实例化,但可以被子类继承使用 public Animal() { } public Animal(int age) { this.Age = age; } //抽象属性不是自动属性 public abstract String Name { get; set; } //抽象类中的抽象方法不能有实现下面的Test()方法会报错,那不是没有方法体,而是有空方法体 //public abstract void Test() //{ //} //抽象方法 public abstract void Bark(); //抽象方法检验函数签名 public abstract string TestString(string name); } public class Dog : Animal { public override void Bark() { Console.WriteLine("狗狗旺旺叫"); } //保持和抽象类中的抽象方法相同 public override string TestString(string name) { throw new NotImplementedException(); } //抽象属性的实现 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 TestString(string name) { throw new NotImplementedException(); } //抽象属性的实现 public override string Name { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } } }
运行结果:
抽象类的练习:
使用多态求矩形的面积和周长,以及圆的面积和周长,分析求矩形的面积和周长以及圆的面积和周长的方式不同所以
求面积和周长的方法我们不能写死,这时可以用抽象类来
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _0120401抽象类练习 { class Program { static void Main(string[] args) { //求矩形的面积和周长以及圆的面积和周长 Method m1 = new Circle(3);//Method m1 = new Rectangle(4,5); double area = m1.GetArea(); double perimeter = m1.GetPerimeter(); Console.WriteLine("圆的面积是{0}\t周长是{1}\t",area,perimeter); Console.ReadKey(); //Method n1 = new Circle(3); //Method n2 = new Rectangle(4, 5); //Method[] mtd = { n1, n2 }; //double area, perimeter; //for (int i = 0; i < mtd.Length; i++) //{ // area = mtd[i].GetArea(); // perimeter = mtd[i].GetPerimeter(); // Console.WriteLine("面积{0}\t周长{1}",area,perimeter); //} //Console.ReadKey(); } } //写一个求周长和面积的抽象类 public abstract class Method { public abstract double GetPerimeter();//求周长的抽象方法 public abstract double GetArea(); //求面积的抽象方法 } public class Circle : Method { 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 Rectangle : Method //矩形类继承与抽象类实现求周长和面积的方法 { 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 Rectangle(double height, double with)//定义构造函数用于初始化 { this.Height = height; this.Width = with; } public override double GetArea()//重写求面积的抽象方法 { return (this.Height * this.Width) * 2; } public override double GetPerimeter()//重写求周长的方法 { return this.Height * this.Width; } } }
类的关系图:
运行结果:
被注释掉的运行结果: