多态性html
首先理解一下什么叫多态。同一操做做用于不一样的对象,能够有不一样的解释,产生不一样的执行结果,这就是多态性。设计模式
多态性经过派生类覆写基类中的虚函数型方法来实现。ide
多态性分为两种,一种是编译时的多态性,一种是运行时的多态性。函数
编译时的多态性:编译时的多态性是经过重载来实现的。对于非虚的成员来讲,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操做。测试
运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际状况决定实现何种操做。C#中运行时的多态性是经过覆写虚成员实现。spa
下面咱们来分别说明一下多态中涉及到的四个概念:重载,覆写,虚方法和抽象方法。设计
重载和覆写的区别:htm
重载对象
类中定义的方法的不一样版本blog
public int Calculate(int x, int y)
public double Calculate(double x, double y)
特色(两必须一能够)
方法名必须相同
参数列表必须不相同
返回值类型能够不相同
覆写
子类中为知足本身的须要来重复定义某个方法的不一样实现。
经过使用override关键字来实现覆写。
只有虚方法和抽象方法才能被覆写。
要求(三相同)
相同的方法名称
相同的参数列表
相同的返回值类型
例:
public class Test
{
public int Calculate(int x, int y)
{
return x + y;
}
public double Calculate(double x, double y)
{
return x + y;
}
}
首先看这个类,咱们在同一个类中知足了重载的三个特色,方法名必须相同Calculate;参数列表必须不相同第一个方法的两个参数类型为int类型,第二个方法的两个参数类型为double类型;返回值类型能够不相同一个返回值类型为int,另外一个返回值类型为double。
而后咱们在客户程序中调用这两个方法。
这时候咱们发现智能提示里提示这个方法已经被重载过一次了。这样咱们就能够根据业务逻辑调用不一样的方法来实现不一样的业务。
客户端测试程序:
Test t = new Test();
int x;
int y;
Console.WriteLine("Please input an integer.\n");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please input another integer.\n");
y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
int result1 = t.Calculate(x,y);
Console.WriteLine("int x + int y = {0}\n",result1.ToString());
double a;
double b;
Console.WriteLine("Please input an double.\n");
a = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Please input another double.\n");
b = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
double result2 = t.Calculate(a,b);
Console.WriteLine("double x + double y = {0}\n",result2.ToString());
Console.ReadLine();
执行结果为:
下面来看一看覆写,咱们将基类(父类)做一下修改
public class Test
{
public virtual int Calculate(int x, int y)
{
return x + y;
}
public virtual double Calculate(double x, double y)
{
return x + y;
}
}
派生类(子类)
public class TestOverride : Test
{
public override int Calculate(int x, int y)
{
return x * y;
}
public override double Calculate(double x, double y)
{
return x * y;
}
}
这是咱们会在客户端的测试程序中发现,咱们既能够访问到覆写后的方法也能访问到覆写前基类的方法,显示被重载3次,其中两次是被覆写的
客户端测试程序
TestOverride t = new TestOverride();
int x;
int y;
Console.WriteLine("Please input an integer.\n");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Please input another integer.\n");
y = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
int result1 = t.Calculate(x,y);
Console.WriteLine("int x * int y = {0}\n",result1.ToString());
double a;
double b;
Console.WriteLine("Please input an double.\n");
a = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Please input another double.\n");
b = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Test class Calculate method result.\n");
double result2 = t.Calculate(a,b);
Console.WriteLine("double x * double y = {0}\n",result2.ToString());
Console.ReadLine();
执行结果为:
这里还有一个须要提的地方就是在子类若是须要访问父类的方法可使用base关键字,例如:
public class TestOverride : Test
{
public override int Calculate(int x, int y)
{
return base.Calculate (x, y);
}
public override double Calculate(double x, double y)
{
return base.Calculate (x, y);
}
}
这样咱们在客户程序进行访问继承Test类TestOverride类的方法时返回的仍是加法运算的结果。
咱们来对重载和覆写做一个比较
|
Override覆写 |
Overload重载 |
位置 |
存在于继承关系的类中 |
存在于同一类中 |
方法名 |
相同 |
相同 |
参数列表 |
相同 |
必须不一样 |
返回值 |
相同 |
能够不相同 |
最后再来介绍一下虚方法和抽象方法
虚方法
声明使用virtual关键字。
调用虚方法,运行时将肯定调用对象是什么类的实例,并调用适当的覆写的方法。
虚方法能够有实现体。
抽象方法
必须被派生类覆写的方法。
能够当作是没有实现体的虚方法。
若是类中包含抽象方法,那么类就必须定义为抽象类,不管是否还包含其余通常方法。
关于虚方法,上面咱们作了一些实验,下面来看一个关于抽象方法的例子。
例:
public class TestOverride : Test
{
public abstract int Calculate(int x, int y);
public abstract double Calculate(double x, double y);
}
在编译的时候会出现一个错误
要求抽象方法必须被报刊在抽象类中,咱们做以下修改
Public abstract class TestOverride : Test
{
public abstract int Calculate(int x, int y);
public abstract double Calculate(double x, double y);
}
这时知足了抽象方法的要求,便可编译经过
一样咱们还能够对其进行覆写,其实这里的覆写就是咱们所说的对于一个抽象的具体实现。如上面离子所示,咱们先用一个抽象类定义了一个测试类并在其中定义了这个类能够作两个整数或者实数的计算操做,至于具体作什么样的计算和怎么计算并无定义,只是声明我能作这些事,而后在它的子类(一个具体的类)中实现了他的定义,咱们要作的是乘法计算。咱们还能够经过另外一个具体的类还定义咱们可能要作的不是乘法计算而是加法计算。代码以下:
public class TestAdd : Test
{
public override int Calculate(int x, int y)
{
return x + y;
}
public override double Calculate(double x, double y)
{
return x + y;
}
}
这样咱们就实现了用抽象类来定义操做,用具体的类还根据不一样状况实现不一样的操做。关于这一点就引出了咱们设计模式中建立型模式中的工厂方法、建造者、抽象工厂方法等(这些是我暂时学到的模式),若是你们想了解这些知识能够参考TerryLee的设计模式系列文章,很经典。
到此为止咱们介绍了C#中多态性涉及的几个概念,但愿对你们的在之后代码结构设计上能有所帮助:)
在这里牢骚几句,如今的项目中变化是一件很日常的事,咱们设计的软件就是要适应这种常常的变化,将项目中的一些变化点封装起来,在业务发生变化的时候咱们能很轻松的应对这种变化。一个软件的一定会通过它生命周期中的各个部分并最后走向死亡,可是咱们能够在设计中经过使软件有能力来应对这些变化来使它的生存期长一些,会为咱们带来更多的价值(哈哈,这些其实就是设计模式所要达到的一些目的)。
但愿你们能今后文中获得一些收获,谢谢:)