多态是面向对象编程提供的特性之一。多态的简单含义是“以多种形式存在”。
也就是说,同一个实体(方法、运算符或对象)可以在不同的场景下执行不同的操作。
多态示例
using System;
class Program
{
// method does not take any parameter
public void greet()
{
Console.WriteLine("Hello");
}
// method takes one string parameter
public void greet(string name)
{
Console.WriteLine("Hello " + name);
}
static void Main(string[] args)
{
Program p1 = new Program();
// calls method without any argument
p1.greet();
//calls method with an argument
p1.greet("Tim");
}
}
输出
Hello Hello Tim
在上面的示例中,我们在 Program
类中创建了两个同名的方法 greet()
。
这里,其中一个 greet()
方法不接受任何参数,并显示 "Hello"
。而另一个 greet()
方法接受一个参数,并显示 "Hello Tim"
。
因此,greet()
方法在不同的场景下表现不同。或者说,greet()
是多态的。
多态的类型
在了解了多态的基本概念后,让我们学习 C# 中的多态类型。
多态有两种类型:
- 编译时多态 / 静态多态
- 运行时多态 / 动态多态
1. 编译时多态
在编译时多态中,编译器在编译时识别正在调用哪个方法。
在 C# 中,我们通过 2 种方式实现编译时多态:
- 方法重载
- 运算符重载
让我们详细讨论其中的每一个。
C# 方法重载
在 C# 类中,如果方法具有
- 不同的参数数量
- 不同的参数类型
例如,
void totalSum() {...}
void totalSum(int a) {...}
void totalSum(int a, int b) {...}
void totalSum(float a, float b) {...}
那么可以在一个类中创建同名的方法。这里我们为 totalSum()
方法提供了不同的参数类型和数量。这在 C# 中称为方法重载。同一个方法将根据参数执行不同的操作。
请看下面的示例,
using System;
class Program
{
// method adds two integer numbers
void totalSum(int a, int b)
{
Console.WriteLine("The sum of numbers is " + (a + b));
}
// method adds two double-type numbers
// totalSum() method is overloaded
void totalSum(double a, double b)
{
Console.WriteLine("The sum of numbers is " + (a + b));
}
static void Main(string[] args)
{
Program sum1 = new Program();
sum1.totalSum(5, 7);
sum1.totalSum(53.5, 8.7);
}
}
输出
The sum of numbers is 12 The sum of numbers is 62.2
在上面的示例中,Program
类包含一个名为 totalSum()
的方法,该方法被重载了。totalSum()
方法会根据传递的参数打印:
- 如果传递两个整数作为参数,则计算整数之和
- 如果传递两个双精度数作为参数,则计算双精度数之和
C# 运算符重载
C# 中的某些运算符与不同的操作数行为不同。例如:
+
运算符被重载用于执行数值加法以及字符串连接,并且
现在让我们看看如何通过运算符重载来实现多态。
+
运算符用于添加两个实体。然而,在 C# 中,+
运算符执行两种操作:
1. 将两个数字相加,
int x = 7;
int y = 5;
int sum = x + y;
Console.WriteLine(sum);
// Output: 12
2. 连接两个字符串,
string firstString = "Harry";
string secondString = "Styles";
string concatenatedString = firstString + secondString;
Console.WriteLine(concatenatedString);
// Output: HarryStyles
这里,我们可以看到 +
运算符在 C# 中被重载以执行两个操作:加法和连接。
2. 运行时多态
在运行时多态中,调用哪个方法是在运行时确定的,而不是在编译时确定的。
运行时多态是通过以下方式实现的:
- 方法重写
让我们详细讨论方法重写。
C# 中的方法重写
在 C# 的继承中,如果父类和子类中都存在同一个方法。那么,子类中的方法就会覆盖父类中同名的方法。这称为方法重写。
在这种情况下,同一个方法在父类和子类中将执行不同的操作。
我们可以使用 virtual
和 override
关键字来实现方法重写。
让我们看下面的例子,
using System;
class Polygon
{
// method to render a shape
public virtual void render()
{
Console.WriteLine("Rendering Polygon...");
}
}
class Square : Polygon
{
// overriding render() method
public override void render()
{
Console.WriteLine("Rendering Square...");
}
}
class myProgram
{
public static void Main()
{
// obj1 is the object of Polygon class
Polygon obj1 = new Polygon();
// calls render() method of Polygon Superclass
obj1.render();
// here, obj1 is the object of derived class Square
obj1 = new Square();
// calls render() method of derived class Square
obj1.render();
}
}
输出
Rendering Polygon... Rendering Square…
在上面的示例中,我们创建了一个父类:Polygon
和一个子类:Square
。
请注意,我们在基类和派生类的方法中分别使用了 virtual
和 override
。这里:
virtual
- 允许派生类重写该方法override
- 指示该方法正在重写基类中的方法
通过这种方式,我们在 C# 中实现了方法重写。
注意:派生类中的方法重写基类中的方法,如果派生类中的方法与基类的方法具有**相同的名称**、**相同的返回类型**和**相同的参数**。
为什么需要多态?
多态允许我们创建一致的代码。在前面的示例中,我们还可以创建另一个方法:renderSquare()
来渲染 Square。
这将完美运行。但是,对于每种形状,我们需要创建不同的方法。这将使我们的代码不一致。
为了解决这个问题,C# 中的多态允许我们创建一个单一的 render()
方法,该方法对于不同的形状会表现出不同的行为。