实现多态的三种方式:虚方法、抽象类、接口
一、虚方法
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。
步骤:1、将父类的方法标记为虚方法 ,使用关键字 virtual
2、子类重写父类的虚方法,使用关键字override
class Program
{
static void Main(string[] args)
{
//父类对象里面装的是子类成员,对象employee依然表现为父类类型
//但由于父类的方法被子类重写,调用的是子类自己的方法
Employee employee= new Manager("张三",5000);
employee.SayHello();
Console.ReadKey();
}
}
/// <summary>
/// 员工类
/// </summary>
public class Employee
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public Employee(string name)
{
this.Name = name;
}
//将父类方法标记为虚方法
public virtual void SayHello()
{
Console.WriteLine("我是普通员工");
}
}
/// <summary>
/// 经理类
/// </summary>
public class Manager:Employee
{
private double _salary;
public double Salary
{
get { return _salary; }
set { _salary = value; }
}
public Manager(string name,double salary):base(name)
{
this.Salary = salary;
}
//重写父类虚方法
public override void SayHello()
{
Console.WriteLine("我是经理,我叫{0}我的薪资是{1}元",this.Name,this.Salary);
}
}
/// <summary>
/// 程序员类
/// </summary>
public class Programer : Employee
{
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
public Programer(string name,int age):base(name)
{
this.Age = age;
}
//重写父类虚方法
public override void SayHello()
{
Console.WriteLine("我是程序员,我{0}岁了",this.Age);
}
}
二、抽象类
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。(例如动物类为父类,猫狗为子类,动物会叫,但具体不知到怎么实现叫这个方法,此时可以将动物类标记为抽象类(使用关键字abstract),将叫这个方法标记为抽象方法)
抽象类特点:
1.抽象成员必须标记为abstract,并且不能有任何实现。
2.抽象成员必须在抽象类中。
3.抽象类不能被实例化
4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。(除非子类也是一个抽象类,则可以不重写)
5.抽象成员的访问修饰符不能是private
6.在抽象类中可以包含实例成员。并且抽象类的实例成员可以不被子类实现
7.抽象类是有构造函数的。虽然不能被实例化。
8、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。
9、如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。
class Program
{
static void Main(string[] args)
{
}
}
public abstract class Animal
{
public abstract void Bark();
}
public class Dog : Animal
{
public override void Bark()
{
Console.WriteLine("小狗汪汪叫");
}
}
三、接口
[public] interface I..able
{
成员;
}
接口的特点:
1、接口是一种规范。只要一个类继承了一个接口,这个类就必须实现这个接口中所有的成员
2、为了多态。接口不能被实例化。也就是说,接口不能new(不能创建对象)
3、接口中的成员不能加“访问修饰符”,接口中的成员访问修饰符默认为public,不能修改。
4、接口中的成员不能有任何实现(“光说不做”,只是定义了一组未实现的成员)。
5、接口中只能有方法、属性、索引器、事件,不能有“字段”和构造函数。
6、接口与接口之间可以继承,并且可以多继承。
7、接口并不能去继承一个类,而类可以继承接口 (接口只能继承于接口,而类既可以继承类,也可以继承接口)
8、一个类可以同时继承一个类并实现多个接口,如果一个子类同时继承了父类A,并实现了接口IA,那么语法上A必须写在IA的前面。class MyClass:A,IA{},因为类是单继承的。
9、当一个抽象类实现接口的时候,需要子类去实现接口。
10、显示实现接口的目的:解决方法的重名问题
什么时候显示的去实现接口:
当继承的接口中的方法和参数一摸一样的时候,要是用显示的实现接口