C#的多态性分为静态多态性和动态多态性。
一、静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为:
1.函数重载
2.运算符重载
1.函数重载
可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明。
本质上是为使同一个类的方法在不同输入下能产生不同的输出,在类里面定义了数个不同内容(可能是输入的参数类型不同或输入的参数个数不同),但方法名相同的方法。
如下:
(1)
using System;
namespace PolymorphismApplication
{
public class TestData
{
public int Add(int a, int b, int c)
{
return a + b + c;
}
public int Add(int a, int b)
{
return a + b;
}
}
class Program
{
static void Main(string[] args)
{
TestData dataClass = new TestData();
int add1 = dataClass.Add(1, 2);
int add2 = dataClass.Add(1, 2, 3);
Console.WriteLine("add1 :" + add1);
Console.WriteLine("add2 :" + add2);
}
}
}
(2)
using System;
namespace PolymorphismApplication
{
class Printdata
{
void print(int i)
{
Console.WriteLine("输出整型: {0}", i );
}
void print(double f)
{
Console.WriteLine("输出浮点型: {0}" , f);
}
void print(string s)
{
Console.WriteLine("输出字符串: {0}", s);
}
static void Main(string[] args)
{
Printdata p = new Printdata();
// 调用 print 来打印整数
p.print(1);
// 调用 print 来打印浮点数
p.print(1.23);
// 调用 print 来打印字符串
p.print("Hello Runoob");
Console.ReadKey();
}
}
}
2.运算符重载
重定义运算符。operator声明。
C# 中运算符重载的能力:
实例如下:
using System;
namespace OperatorOvlApplication
{
class Box
{
private double length; // 长度
private double breadth; // 宽度
private double height; // 高度
public double getVolume()
{
return length * breadth * height;
}
public void setLength( double len )
{
length = len;
}
public void setBreadth( double bre )
{
breadth = bre;
}
public void setHeight( double hei )
{
height = hei;
}
// 重载 + 运算符来把两个 Box 对象相加
public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
}
class Tester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 声明 Box1,类型为 Box
Box Box2 = new Box(); // 声明 Box2,类型为 Box
Box Box3 = new Box(); // 声明 Box3,类型为 Box
double volume = 0.0; // 体积
// Box1 详述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// Box2 详述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// Box1 的体积
volume = Box1.getVolume();
Console.WriteLine("Box1 的体积: {0}", volume);
// Box2 的体积
volume = Box2.getVolume();
Console.WriteLine("Box2 的体积: {0}", volume);
// 把两个对象相加
Box3 = Box1 + Box2;
// Box3 的体积
volume = Box3.getVolume();
Console.WriteLine("Box3 的体积: {0}", volume);
Console.ReadKey();
}
}
}
二、动态多态性
都采用override重写方法。
1.抽象类
C#允许把类和函数声明为abstract。
抽象类不能实例化,抽象类可以包含普通函数和抽象函数。
抽象函数就是只有函数定义没有函数体的函数。显然,抽象函数本身也是虚拟(Virtual)的。
类是一个模板,那么抽象类就是一个不完整的模板。我们自然不可以使用不完整的模板去构造对象。
抽象类的声明如下:
abstract class Building
{
public abstract decimal CalculateHeatingCost();
}
注意:
(1)当一个类中如果有方法被声明为abstract时,这个类也要被声明为abstract。
(2)当继承一个抽象类时,必须去实现抽象方法(就是填充函数内容)。
(3)可以用抽象类去声明,但是不能用抽象类去构造。
(4)在抽象方法声明中不能使用static或virtual修饰符。
抽象类的使用如下:
using System;
namespace PolymorphismApplication
{
//抽象类
abstract class Bird
{ //含有抽象方法,就一定是抽象类
private float speed;
public abstract void Fly(); //抽象方法
}
//派生类
class Crow : Bird
{ //继承了抽象类,此时必须要求实现抽象方法
public override void Fly() //override重写方法
{
Console.WriteLine("Crow is flying!");
}
}
class RectangleTester
{
static void Main(string[] args)
{
//用派生类构造和声明
Crow crow = new Crow;
crow.Fly();
//用抽象类声明,用派生类构造
Bird bird = new Crow();
bird.Fly();
}
}
}
2.虚方法
virtual声明,override重写。
与抽象类的区别:
虚方法 | 抽象方法 |
---|---|
用virtual修饰 | 用abstract修饰 |
要用方法体,哪怕是一个分号 | 不允许有方法体 |
可以被子类override(重写) | 必须被子类override(重写) |
除了密封类都可以写 | 只能在抽象类中 |
虚方法可以在不同的继承类中有不同的实现:
using System;
using System.Collections.Generic;
public class Shape
{
public int X { get; private set; }
public int Y { get; private set; }
public int Height { get; set; }
public int Width { get; set; }
// 虚方法
public virtual void Draw()
{
Console.WriteLine("执行基类的画图任务");
}
}
class Circle : Shape
{
public override void Draw()
{
Console.WriteLine("画一个圆形");
base.Draw();
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("画一个长方形");
base.Draw();
}
}
class Triangle : Shape
{
public override void Draw()
{
Console.WriteLine("画一个三角形");
base.Draw();
}
}
class Program
{
static void Main(string[] args)
{
// 创建一个 List<Shape> 对象,并向该对象添加 Circle、Triangle 和 Rectangle
var shapes = new List<Shape>
{
new Rectangle(),
new Triangle(),
new Circle()
};
// 使用 foreach 循环对该列表的派生类进行循环访问,并对其中的每个 Shape 对象调用 Draw 方法
foreach (var shape in shapes)
{
shape.Draw();
}
Console.WriteLine("按下任意键退出。");
Console.ReadKey();
}
}
参考资料链接:
https://blog.csdn.net/lym940928/article/details/79841135
https://www.runoob.com/csharp/csharp-polymorphism.html