C#多态性
文章目录
什么是多态
多态是同一个行为具有多个不同表现形式或形态的能力
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为“一个接口,多个功能”
多态性分为静态和动态。
静态多态性:函数的响应是在编译时发生的。
动态多态性:函数的响应实在运行时发生的。
在C#中,每个类型都是多态的,因为包括用户自定义类型在内的所有类型,都继承于Object
静态多态性
在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。
C#提供了两种技术来实现静态多态性。分别是:
函数重载
运算符重载
函数重载
我们可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同,但是不能重载只有返回类型不同的函数声明。
即:函数重载只与参数类型和个数有关,与函数返回值类型无关
实例如下:
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);
}
}
}
运算符重载
我们可以重定义或重载C#中内置的运算符。
程序员也可以使用用户自定义类型的运算符。
重载运算符时具有特殊名称的函数,时通过关键字operator后跟运算符的符号来定义的。
与其他函数一样,重载运算符有返回类型和参数列表。
运算符重载就是给某一些运算符赋予新的计算逻辑,运算符重载就是一个方法。
运算符重载的要求
1.访问权限必须时public
2.方法必须是static
3.在运算符重载中,必须有operator来修饰
4.返回值类型可以是除了void之外的任意类型
5.参数限制:
(1)参数列表中,至少要包含一个当前类型。
(2)参数的数量不是随意的,要和运算符能够操作的运算数量匹配。
(3)三元运算符不允许重载。
可以重载的运算符
可以重载的运算符:
+、-、*、/、%、++、–;&、|、!、^;~、>、<、>=、<=、==、!=
关系运算符要是重写的话,需要成对重写,否则会在运算符处报错。
运算符重载的语法
public static [返回值类型] operator [运算符]
{
}
运算符重载实例
实例1:
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();
}
}
}
实例2:
class Program
{
static void Main(string[] args)
{
BoxCompute tmp = new BoxCompute();
tmp.length = 10;
tmp.width = 20;
tmp.height = 30;
BoxCompute tmp2 = 2 * tmp ;
Console.WriteLine(tmp2.length);
}
}
class BoxCompute
{
public float length;
public float width;
public float height;
/// <summary>
/// 计算箱子 体积
/// </summary>
/// <returns></returns>
public static float BoxComputeVolume(float length,float width,float height)
{
return length * width * height;
}
/// <summary>
/// 计算箱子 面积之和
/// </summary>
/// <returns></returns>
public static float BoxComputeAreaTotal(float length,float width,float height)
{
return length * width * 2 + length * height * 2 + width * height * 2;
}
/// <summary>
/// 计算两个箱子长宽高相加之后的箱子
/// </summary>
/// <param name="firstBox"></param>
/// <param name="secondBox"></param>
/// <returns></returns>
public static BoxCompute operator +(BoxCompute firstBox,BoxCompute secondBox)
{
BoxCompute result = new BoxCompute();
result.length = firstBox.length + secondBox.length;
result.width = firstBox.width + secondBox.width;
result.height = firstBox.height + secondBox.height;
return result;
}
/// <summary>
/// 箱子长宽高等比缩放
/// </summary>
/// <param name="multipleNum"></param>
/// <param name="tmpBox"></param>
/// <returns></returns>
public static BoxCompute operator *(float multipleNum, BoxCompute tmpBox)
{
BoxCompute result = new BoxCompute();
result.length = tmpBox.length * multipleNum;
result.width = tmpBox.width * multipleNum;
result.height = tmpBox.height * multipleNum;
return result;
}
}
}
动态多态性
多态的本质就是:父类的引用可以指向子类的对象
方法的隐藏和重写
在动态多态性中,一定会涉及到方法的隐藏和重写
方法的隐藏
在父类和子类中有相同的方法时,子类会自动隐藏父类中的方法
方法的重写
关键字:virture-虚
用来修饰方法。
作用:
虚方法可以被子类隐藏,也可以被重写;
非虚方法只能被子类隐藏,不能被重写
关键字:override -重写
重写:又叫覆写,指的是将父类的方法重新实现
所以,要想对方法重写,那么必须将原方法改为虚方法:即在原方法上加上virture关键字即可。然后在子类中重写的时候,需要在子类的方法中加上override关键字修饰
注意:只有虚方法或者抽象方法(abstract)才能够重写
抽象类
关键字:abstract
抽象类:用abstract修饰的类就是抽象类。
抽象类的特点:
1.抽象类不能实例化对象(与静态类相似)。
2.抽象类中可以写非静态成员(与静态类相反)。
3.抽象类可以继承,所以非静态成员是给子类用的。
C#允许使用关键字abstract创建抽象类,用于提供接口的部分类的实现。
当一个派生类集成自该抽象类时,实现即完成。
抽象类包含抽象方法,抽象方法可以被派生类实现。派生类具有更专业的功能。
抽象类的规则
1.不能创建一个抽象类的实例
2.不能再一个抽象类外部声明一个抽象方法
3.通过类定义前面放置关键字sealed,可以将类声明为密封类。当一个类被声明为sealed时,它不能被继承。所以抽象类不能被声明为sealed
抽象类的实例
class Program
{
static void Main(string[] args)
{
Box box = new Box();
box.length = 10;
box.width = 20;
box.height = 30;
Console.WriteLine("该箱子的体积是:"+box.Volume());
//输出为: 该箱子的体积为:6000
Sphere sphere = new Sphere();
sphere.radius = 22;
Console.WriteLine("该球体的体积是:"+sphere.Volume());
//输出为: 该球体的体积为:44602.24
}
}
abstract class Sharp
{
public int length;
public int width;
public int height;
public float radius;
public abstract float Volume();
}
class Box : Sharp
{
//override是重写,只有abstract和virture修饰的方法,才能在子类中重写
public override float Volume()
{
float volume = this.length * this.width * this.height;
return volume;
}
}
class Sphere : Sharp
{
public override float Volume()
{
float volume =(float)( Math.Pow(this.radius, 3) * Math.PI * 4 / 3);
return volume;
}
}
普通类
普通类的多态性
相比较于抽象类,没有抽象类多态的限制
普通类不需要一定实现父类中的方法,而实现抽象类的则必须实现抽象父类中的抽象方法
普通类的多态实例
class Program
{
static void Main(string[] args)
{
Person person = new Person();
Dog dog = new Dog();
person.ShowAnimalClass();
dog.ShowAnimalClass();
}
}
class Animal
{
public bool gender;
public int age;
public string animalClass;
public void ShowGender()
{
Console.WriteLine("性别为:"+this.gender);
}
public void ShowAge()
{
Console.WriteLine("年龄为:"+this.age);
}
public void ShowAnimalClass()
{
Console.WriteLine("动物种类为:"+this.animalClass);
}
}
class Person : Animal
{
public Person()
{
this.animalClass = "人类";
}
//方法的隐藏
public void ShowGender()
{
Console.WriteLine("隐藏父类中的ShowGender方法"+":默认男的");
}
//方法的隐藏
public new void ShowAge()
{
Console.WriteLine("就不告诉你");
}
}
class Dog : Animal
{
public Dog()
{
this.animalClass = "犬科";
}
}