C#小笔记——多态性

面向对象语言三大特性:封装、继承、多态

多态:一个接口多个功能。
C#小笔记——多态性_第1张图片
多态性可以是静态的或动态的。

函数重载和运算符重载实现静态多态性。抽象类和虚方法共同实现动态多态性。

在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

1、重载(overload): 在同一个作用域(一般指一个类)的两个或多个方法函数名相同,参数列表不同的方法叫做重载,它们有三个特点(俗称两必须一可以):

• 方法名必须相同
• 参数列表必须不相同
• 返回值类型可以不相同

例如:

public void Test()
{
	Console.WriteLine("睡觉");
}
public int Test(int time)
{
	Console.WriteLine("{0}点睡觉",time);
	return time;
}

2、重写(override): 只有基类成员声明为virtual或abstract时,才能被派生类重写,而如果子类想改变虚方法的实现行为,则必须使用override关键字。它的特点是(三个相同):

• 相同的方法名
• 相同的参数列表
• 相同的返回值

例如:

public class you
{
	public virtual void talk()
	{
		Console.WriteLine("one");
    }
}
public class my : you
{
	public override void talk()
	{
		Console.WriteLine("two");
	}
}

小结一下重载和重写的区别:

区别 \ 名称 重载 重写
范围 同一个类 不同的类
方法名 相同 相同
参数列表 不同 相同
修饰符 无关 大于父类方法
抛出父类没有的异常 可以 不可以
返回类型 不同 相同
与面向对象 多态 继承

3、抽象类(abstract): 在基类中定义的并且必须在派生类中重写的方法,使用 abstract 关键字定义,如

//包含抽象函数的类,类也必须定义为抽象的(抽象函数只能在抽象类中定义)
public abstract class Biology
{
    public abstract void Live();//抽象函数不能有函数体,且修饰符必须是 public
	
	void Talk()//抽象类中可以包含普通函数
	{
	}
}
public class Animal : Biology
{
    public override void Live()
    {
        Console.WriteLine("Animal重写的抽象方法");
    } 
}

注意:可以声明抽象类的对象。但是不可以实例化对象。必须依靠子类来实例化。

public abstract class Test
{
	public abstract void Attack();
}
public class Boss : Test
{
	public override void Attack()
	{
	}
}
class Program
{
	static void Main(string[] args)
	{	
		Boss b = new Boss();
		b.Attack();
	}
}

4、虚方法(virtual): 即为基类中定义的允许在派生类中重写的方法,使用 virtual 关键字定义,如

public class Test
{
	public virtual void talk()
	{
		Console.WriteLine("one");
    }
}

注意:虚方法也可以被直接调用

Test t = new Test();
t.talk();

virtual (虚方法) 和 abstract (抽象方法) 的区别

virtual 和 abstract 都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义。

  • virtual 修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而 abstract 修饰的方法一定不能实现。
  • virtual 可以被子类重写,而 abstract 必须被子类重写。
  • 如果类成员被 abstract 修饰,则该类前必须添加 abstract,因为只有抽象类才可以有抽象方法。
  • 无法创建 abstract 类的实例,只能被继承无法实例化。

5、隐藏方法: 如果签名相同的方法在基类和派生类中都进行了声明,但是该方法没有分别声明为virtual和override,派生类就会隐藏基类方法。(要使用new关键字进行声明)

public class Student
{
	public virtual void Exam()
	{
		Console.WriteLine("学生都要考试");
	}
}
public class Undergraduate:Student
{
	public new void Exam()
	{//隐藏方法
		base.Exam();
		Console.WriteLine("大学生有选择考试科目的权利");
	}
}

注意:

(1)隐藏方法不但可以隐藏基类中的虚方法,而且也可以隐藏基类中的非虚方法。

(2)隐藏方法中父类的实例调用父类的方法,子类的实例调用子类的方法。

(3)重写方法中子类的变量调用子类重写的方法,父类的变量要看这个父类引用的是子类的实例还是本身的实例。如果引用的是父类的实例,那么调用基类的方法;如果引用的是派生类的实例,则调用派生类的方法。

虚方法的调用: 调用上,使用子类构造的对象调用虚方法,就会调用子类的方法,使用父类构造的对象,就会调用父类的方法。

隐藏方法的调用: 调用上, 使用子类类型的声明调用隐藏方法,就会调用到子类的方法。若想调用被隐藏的方法,需要用父类类型的声明来调用。

你可能感兴趣的:(C#学习之记笔记)