多态是面向对象编程中三大机制之一,其原理建立在"从父类继承而来的子类可以转换为其父类"这个规则之上,换句话说,能用父类的地方,就能用该类的子类.当从父类派生了很多子类时,由于每个子类都有其不同的代码实现,所以当用父类来引用这些子类时,同样的操作而可以表现出不同的操作结果,这就是所谓的多态. (多态就是对象可以表型多个类型的能力)
几种建立多态的方式:
1、用父类实现多态
2、用抽象了实现多态
3、用接口实现多态
多态——隐藏基类方法与多态实现(子类重写父类的方法)
1、子类可以有与父类方法名相同的方法:签名不同(重载)、签名相同(隐藏基类方法)
2、子类可以重写父类方法:虚方法、重写方法、重写基类方法一样可以调用基类方法
虚方法:
1、用virtual修饰的方法
2、虚方法可以在子类中通过override关键字来重写
3、常见的虚方法:ToString()Equals
虚方法和重写方法的一些特点:
1、方法不能用static修饰
2、方法重写与基类的签名必须一致
3、virtual不能与private一起使用
例子:
namespace _03_多态
{
class Program
{
static void Main(string[] args)
{
// 子类的方法名可以和父类的方法名重名;----但是会出现一条绿线,瑕疵
//怎么解决:可以在子类方法的修饰符后面加new就解决了
//无论是否加new 都不影响使用
//第二种解决绿线的方法:
//可以在父类的方法的修饰符后面加 virtual
//在子类中重写父类的方法,加上一个override;调用父类的方法,但是把父类的方法进行重写了
//更换了方法里面的内容
Person p =new Person();
p.Show();
Teacher t = new Teacher();
t.Show();
Console.ReadKey();
}
}
public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
public virtual void Show()//虚方法 ----
{
Console.WriteLine("我是人别害怕");
}
public void Say()
{
Console.WriteLine("hello");
}
}
public class Teacher : Person
{
public override void Show()
{
Console.WriteLine("我是老师");
}
}
}
多态——抽象方法与抽象类
抽象类与抽象方法:
1、抽象类与抽象方法由abstract修饰
2、abstract的使用注意
(1)抽象方法没有方法体
(2)抽象成员只能存在于抽象类中
(3)抽象类可以有非抽象成员
(4)抽象类的派生类必须实现抽象方法体
(5) 抽象类只能用作基类,无法实例化
3、父类是抽象类,子类继承了这个类,必须把抽象类中的抽象方法重写
例子:
namespace _05_多态练习
{
class Program
{
static void Main(string[] args)
{
//随机产生10个类的对象
//放在数组里,之后遍历这个数组,把方法调出来
//Animal 猪 狗 猫 牛 鸟
Animal[] animal = new Animal[10];
Random r = new Random();
for (int i = 0; i < animal .Length ; i++)
{
int num = r.Next(1, 5);
switch (num)
{
case 1:animal[i] = new Pig("小赵");break;
case 2: animal[i] = new Dog ("老牛"); break;
case 3: animal[i] = new Cow ("老苏"); break;
case 4 : animal[i] = new Cat ("老黄"); break;
}
}
for (int i = 0; i < animal.Length ; i++)
{
animal[i].Shout();
}
Console.ReadKey();
}
}
public abstract class Animal
{
public Animal(string name)
{
this._name = name;
}
string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public abstract void Shout();
}
public class Pig : Animal
{
public Pig(string name)
: base(name)
{
}
public override void Shout()
{
Console.WriteLine("{0}哼哼...",this .Name );
}
}
public class Dog : Animal
{
public Dog (string name)
: base(name)
{
}
public override void Shout()
{
Console.WriteLine("{0}旺旺...",this .Name );
}
}
public class Cow : Animal
{
public Cow (string name)
: base(name)
{
}
public override void Shout()
{
Console.WriteLine("{0}哞哞叫",this .Name );
}
}
public class Cat : Animal
{
public Cat (string name)
: base(name)
{
}
public override void Shout()
{
Console.WriteLine("{0}喵喵叫",this .Name );
}
}
虚方法与抽象方法比较:
多态——接口
接口:
1、接口的定义:Interface关键字,接口中可以有属性、方法(未实现)
2、接口的名称通常以“I”开头,例如:IList
3、如果一个类即继承了类又实现了接口,那么类必须写在前面。一个类只能继承一个父类,但可以实现多个接口
4、class Student:Person,IComparable
5、完全抽象的一种约定,接口就是用来实现的
语法:
[访问修饰符] interface 接口名
{
//接口成员定义
}
Interface Ifly
{
//void IFly();
}
例子:接口的实现
namespace _06_接口
{
class Program
{
static void Main(string[] args)
{
Ifly ifly = new Student();//又是多态的体现形式
ifly.Ifly();
Console.ReadKey();
}
}
public class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
public void Show()
{
Console.WriteLine("我是人别害怕");
}
}
public class Teacher : Person,Ifly
{
public void Say()
{
Console.WriteLine("我是老师");
}
public void Ifly()
{
Console.WriteLine("我ye会飞");
}
}
public class Student :Ifly
{
public void SayHello()
{
Console.WriteLine("我是学生");
}
public void Ifly()
{
Console.WriteLine("我会飞");
}
}
}
C#中的接口和类的异同:
不同点:
1、不能直接实例化接口
2、接口不包含方法的实现
3、接口可以多继承,类只能单继承
4、类定义可在不同的源文件之间进行拆分
相同点:
1、接口、类和结构都可以从多个接口继承。
2、接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员
3、接口和类都可以包含事件、索引器、方法、属性
abstract class与interface的异同:
相同点:
都不能被直接实例化,都可以通过继承实现其抽象方法。
不同点:
1、 接口支持多继承;抽象类不能实现多继承
2、接口只能定义行为;抽象类既可以定义行为,还可能提供实现
3、接口可以用于支持回调(CallBack),抽象类不能实现回调,因为继承不支持
4、接口只包含方法(Method)、属性(Property)、索引器(Index)、事件(Event)的签名,但不能定义字段和包含实现的方法
5、抽象类可以定义字段、属性、包含实现类
6、接口可以作用于值类型(Struct)和引用类型(Class);抽象类只能作用于引用类型