一、多态
让一个对象能够表现出多种状态(类型)
1.实现多态的手段
1)、虚方法
步骤:
1、将父类的方法标记为虚方法,使用关键字virtual,这个函数可以被子类重新写一个遍。子类方法前面override.
namespace Pratise
{
class Lianxi
{
static void Main(string[] arg)
{
Teacher t = new Teacher();
Principal p = new Principal();
Employee e = new Employee();
Employee[] es = { t, p ,e};
for (int i = 0; i < es.Length; i++)
{
es[i].ClockIn();
}
Console.ReadKey();
}
}
public class Employee
{
public virtual void ClockIn()
{
Console.WriteLine("开始打卡");
}
}
public class Teacher:Employee
{
public override void ClockIn()
{
Console.WriteLine("九点开始打卡");
}
}
public class Principal : Employee
{
public override void ClockIn()
{
Console.WriteLine("不限制时间");
}
}
}
2)、抽象类
当父类中的方法不知道如何去实现的时候,可以考虑将父类写成抽象类,将方法写成抽象方法。
namespace Pratise
{
class Abstract
{
static void Main(string[] arg)
{
An a = new Dog();//new Cat();
a.bark();
Console.ReadKey();
}
}
public abstract class An
{
//抽象方法是不允许有方法体的
public abstract void bark();
}
public class Dog : An
{
public override void bark()
{
Console.WriteLine("狗叫");
}
}
public class Cat : An
{
public override void bark()
{
Console.WriteLine("猫叫");
}
}
}
二、抽象类
1.抽象成员必须标记为abstract,并且不能有任何实现。
2.抽象成员必须抽象类中。
3.抽象类不能被实例化~
4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。
(除非子类也是一个抽象类,则可以不重写)
5.抽象成员的访问修符不能是private,并且抽象类的实例成员可以不被子类实现
6.抽象类是有构造函数的。虽然不能被实例化。
7、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。
如果拍象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候也必须要传入返回值。
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。
如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。
练习
用多态来实现将移动硬盘或者u盘或者Mp3插到电脑上进行读写数据
namespace Pratise
{
class MoNi
{
static void Main(string[] arg)
{
//用多态来实现将移动硬盘或者u盘或者Mp3插到电脑上进行读写数据
//MobileDisk md = new MobileDisk();
//UDisk u = new UDisk();
//MP3 mp3 = new MP3();
//Computer cpu = new Computer();
//cpu.CpuRead(u);
//cpu.CpuWrite(u);
MobileStorge ms = new UDisk();//MP3();//MobileDisk();
Computer cpu = new Computer();
cpu.Ms = ms;
cpu.CpuRead();
cpu.CpuWrite();
//Computer cpu=new Computer();
//cpu.CpuRead(ms);
//cpu.CpuWrite(ms);
Console.ReadKey();
}
}
///
/// 抽象的父类
///
public abstract class MobileStorge
{
public abstract void Read();
public abstract void Write();
}
public class MobileDisk : MobileStorge
{
public override void Read()
{
Console.WriteLine("移动硬盘在读取数据");
}
public override void Write()
{
Console.WriteLine("移动硬盘在写入数据");
}
}
public class UDisk : MobileStorge
{
public override void Read()
{
Console.WriteLine("优盘正在读取数据");
}
public override void Write()
{
Console.WriteLine("优盘正在写入数据");
}
}
public class MP3 : MobileStorge
{
public void PlayMusic()
{
Console.WriteLine("播放音乐中");
}
public override void Read()
{
Console.WriteLine("mp3正在读数据");
}
public override void Write()
{
Console.WriteLine("mp3正在写入数据");
}
}
public class Computer
{
private MobileStorge _ms;
public MobileStorge Ms
{
get { return _ms; }
set { _ms = value; }
}
public void CpuRead()
{
Ms.Read();
}
public void CpuWrite()
{
Ms.Write();
}
}
}
求矩形的面积和周长以及圆形的面积和周长
namespace Pratise
{
class Area
{
static void Main(string[] arg)
{
//求矩形的面积和周长以及圆形的面积和周长
Shape shape = new Square(5, 6);//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 Math.PI * this.R * 2;
}
}
//矩形
public class Square : Shape
{
private double _height;
public double Height
{
get { return _height; }
set { _height = value; }
}
private double _weight;
public double Weight
{
get { return _weight; }
set { _weight = value; }
}
public Square(double height, double weight)
{
this.Height = height;
this.Weight = weight;
}
public override double GetArea()
{
return this.Height * this.Weight;
}
public override double GetPerimeter()
{
return (this.Height + this.Weight)*2;
}
}
}
}