using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 多态
{
class Program
{
static void Main(string[] args)
{
//员工9点打卡, 经理11点打卡,程序员不打卡
Employee emp = new Employee();
emp.Daka();
Manager man = new Manager();
man.Daka();
Programer pro = new Programer();
pro.Daka();
Console.WriteLine();
//和上面的一样
Employee[] emps = { emp, man, pro };
for (int i = 0; i < emps.Length;i++ )
{
//if(emps[i] is Manager)
//{
// ((Manager)emps[i]).Daka();
//}
//else if(emps[i] is Programer)
//{
// ((Programer)emps[i]).Daka();
//}
//else
//{
// emps[i].Daka();
//}
emps[i].Daka();
emps[i].Say();
emps[i].Speak("Hello bad cat");
}
//抽象类不能创建对象,不能被实例化
//Person per = new Person();
Console.ReadKey();
}
}
//如果父类的方法没有默认实现,并且父类不需要被实例化
//这时可以考虑将父类定义成一个抽象类
abstract class Person
{
//抽象类不能创建对象
//抽象类中可以含有字段、实函数和虚函数等普通成员,可以不被子类重写
public string Name { get; set; }
public int Age { get; set; }
public void Say()
{
Console.WriteLine("hello");
}
//虚函数,可以实现,可以不实现
public virtual void Daka()
{
Console.WriteLine("virtual hello");
}
//如果用户定义了自己的构造函数,而在子类继承时调用的是原先的默认的无参构造函数
//因此要再定义一个无参的构造函数
public Person(string name,int age)
{
this.Name = name;
this.Age = age;
}
//抽象类有构造函数,虽然不能被实例化
public Person()
{ }
//抽象类中可以具有抽象成员,并且不能是private
//抽象成员必须标记为abstract,并且不能在抽象类中实现
//抽象成员必须在抽象类中
public abstract void SayHi();
//带有参数的抽象成员
public abstract void Speak(string words);
}
//子类也是抽象类,可以不实现父类的抽象成员
abstract class test:Person
{
}
//如果父类的方法有默认实现,并且父类需要被实例化
//可将父类定义成一个普通类,用虚方法实现多态
//对于继承抽象类的子类,必须将父类中的抽象成员都重写
//除非子类也是抽象类
class Employee:Person
{
//public override void Daka()
//{
// Console.WriteLine("9点打卡");
//}
//没有实现时运行Person中的virtual hello
public override void SayHi()
{ }
public override void Speak(string words)
{
Console.WriteLine(words);
}
}
//如果抽象类继承抽象类,并且可以不实现抽象类中的抽象函数
abstract class MyEmployee:Person
{
}
class Manager : Employee
{
public override void Daka()
{
Console.WriteLine("11点打卡");
}
}
class Programer : Employee
{
public override void Daka()
{
Console.WriteLine("不打卡");
}
}
}
总结
1.抽象成员必须标记为abstract,并且不能有任何实现。
2.抽象成员必须在抽象类中。
3.抽象类不能被实例化
4.子类继承抽象类后,必须把父类中的所有抽象成员都重写。
(除非子类也是一个抽象类,则可以不重写)
5.抽象成员的访问修饰符不能是private
6.在抽象类中可以包含实例成员。
并且抽象类的实例成员可以不被子类实现
7.抽象类是有构造函数的。虽然不能被实例化。
8、如果父类的抽象方法中有参数,那么。继承这个抽象父类的子类在重写父类的方法的时候必须传入对应的参数。
如果抽象父类的抽象方法中有返回值,那么子类在重写这个抽象方法的时候 也必须要传入返回值。
======
如果父类中的方法有默认的实现,并且父类需要被实例化,这时可以考虑将父类定义成一个普通类,用虚方法来实现多态。
如果父类中的方法没有默认实现,父类也不需要被实例化,则可以将该类定义为抽象类。
练习
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/*
* 模拟将外部的移动设备查到电脑上进行读写
* U 盘read、write
*
* 移动硬盘read、write
*
* MP3 read write playmusic
*/
namespace 抽象类练习
{
class Program
{
static void Main(string[] args)
{
UDisk udisk = new UDisk();
MobileDisk mdisk = new MobileDisk();
Mp3 mp3 = new Mp3();
Computer cpu = new Computer();
cpu.ds = udisk;
cpu.CpuWrite(cpu.ds);
cpu.CpuRead(cpu.ds);
Console.WriteLine();
Telephone tel = new Telephone();
tel.ds = mdisk;
tel.TelWrite();
tel.TelRead();
Console.ReadKey();
}
}
abstract class Disk
{
public abstract string Read();
public abstract void Write(string str);
}
class UDisk:Disk
{
public override string Read()
{
Console.WriteLine("U Read");
string str = "U Read";
return str;
}
public override void Write(string str)
{
Console.WriteLine("U write" + str);
}
}
class MobileDisk:Disk
{
public override string Read()
{
Console.WriteLine("MobileDisk Read");
string str = "MobileDisk Read";
return str;
}
public override void Write(string str)
{
Console.WriteLine("MobileDisk Write"+str);
}
}
class Mp3:Disk
{
public override string Read()
{
Console.WriteLine("Mp3 Read");
string str = "Mp3 Read";
return str;
}
public override void Write(string str)
{
Console.WriteLine("Mp3 Write"+str);
}
public void PlayMusic()
{
Console.WriteLine("Mp3 is playing music");
}
}
class Computer
{
public Disk ds { get; set; }
public void CpuRead(Disk disk)
{
string str = disk.Read();
//
}
public void CpuWrite(Disk disk)
{
string str = "Cpu ";
disk.Write(str);
}
public Computer()
{
Console.WriteLine("Cpu:");
}
}
class Telephone
{
public Disk ds { get; set; }
public void TelRead()
{
string str = ds.Read();
//Console.WriteLine(str);
}
public void TelWrite()
{
string str = "Tel ";
ds.Write(str);
}
public Telephone()
{
Console.WriteLine("Tel:");
}
}
}