unity的C#学习 您所在的位置:网站首页 编程多态性的英文 unity的C#学习

unity的C#学习

2024-07-15 19:24| 来源: 网络整理| 查看: 265

文章目录 多态性1、静态多态性1.1 函数重载——利用参数差异1.2 运算符重载——operator 2、动态多态性2.1 抽象类/成员——abstract2.2 不可继承类/方法——sealed2.3 虚方法——virtual

多态性

多态是同一个行为具有多个不同表现形式或形态的能力。多态性意味着有多重形式,在面向对象编程范式中,多态性往往表现为“一个接口,多个功能”。

多态性可以是静态的或动态的:

在静态多态性中,函数的响应是在编译时发生的,主要借由重载(overload)实现。在动态多态性中,函数的响应是在运行时发生的,主要借由重写(override)实现。

在 C# 中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自Object。多态就是同一个接口,使用不同的实例而执行不同操作。

简单来说,就是同一个事件发生在不同的对象上会产生不同的结果。例如现实中我们按下 F1 键这个动作:

如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。 1、静态多态性

在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定,这种静态绑定就是构成静态多态的关键。换句话说,静态多态是指在编译时就能够确定具体调用哪个函数的多态性。C# 提供了两种技术来实现静态多态性。分别为:

函数重载运算符重载 1.1 函数重载——利用参数差异

我们可以在同一个范围内对相同的函数名有多个定义,但函数的定义必须彼此不同:

可以是参数列表中的参数类型不同。可以是参数个数不同。只有返回类型不同的函数声明不能重载。

下面的实例演示了几个相同的函数 Add(),用于对不同个数参数进行相加处理:

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); } } }

下面的实例演示了几个相同的函数 print(),用于打印不同的数据类型:

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(); } } }

当上面的代码被编译和执行时,它会产生下列结果:

输出整型: 1 输出浮点型: 1.23 输出字符串: Hello Runoob

1.2 运算符重载——operator

我们可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用自定义类型的运算符,来指定类对象之间的运算操作。

重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。

重载运算符的语法格式为:

public static 返回类型 operator 运算符(参数列表) { // 实现运算符的操作 return 运算结果; }

其中,返回类型可以是任何有效的C#类型,参数列表可以包含一个或多个输入参数。

重载运算符必须是public和static关键字修饰的,并且必须定义在类或结构体中,因此只会影响定义或继承了重载运算符的类或结构体的运算。 运算符描述+(正), -(负), !, ~, ++, –这些一元运算符只有一个操作数,且可以被重载。+, -, *, /, %这些二元运算符带有两个操作数,且可以被重载。==, !=, , =这些比较运算符可以被重载。&&, ||这些条件逻辑运算符不能被直接重载。+=, -=, *=, /=, %=这些赋值运算符不能被重载 。=, ., ?:, ->, new, is, sizeof, typeof这些运算符不能被重载 。

下面是一个简单的例子,演示了如何重载加法运算符:

class Vector { public int X { get; set; } public int Y { get; set; } public Vector(int x, int y) { X = x; Y = y; } public static Vector operator +(Vector a, Vector b) //重载加法运算符,仅影响Vector对象的加法运算 { return new Vector(a.X + b.X, a.Y + b.Y); //在重载运算符函数内部并不是对Vector对象的运算,而是对于其字段的运算,所以不受影响 } } class Program { static void Main(string[] args) { Vector a = new Vector(1, 2); Vector b = new Vector(3, 4); Vector c = a + b; Console.WriteLine("c = ({0}, {1})", c.X, c.Y); } }

在这个例子中,定义了一个Vector类,其中重载了加法运算符。当使用加法运算符对两个Vector对象进行加法运算时,将调用该类中定义的加法运算符函数,完成运算操作。

子类可以继承父类中定义的运算符重载,但是子类也可以选择覆盖这些运算符重载,以便自定义子类特定的行为。注意这里的覆写是函数重载,和后面的虚函数不一样:

using System; // 定义基类 A class A { // 定义公有成员变量 X public int X; // 定义构造函数,初始化 X public A(int x) { X = x; } // 定义运算符重载,实现 A 之间的加法操作 public static A operator +(A a, A b) { return new A(a.X + b.X); } } // 定义派生类 B,继承自 A class B : A { // 定义公有成员变量 Y public int Y; // 定义构造函数,初始化 X 和 Y public B(int x, int y) : base(x) { Y = y; } // 子类覆写运算符重载,实现 B 之间的加法操作 public static B operator +(B a, B b) { return new B(a.X + b.X, a.Y + b.Y); } } // 定义入口类 Program class Program { static void Main(string[] args) { // 实例化 A 对象 a1 和 a2,以及其加法运算的结果 a3 A a1 = new A(1); A a2 = new A(2); A a3 = a1 + a2; Console.WriteLine("a1 + a2 = " + a3.X); // 实例化 B 对象 b1 和 b2,以及其加法运算的结果 b3 B b1 = new B(1, 2); B b2 = new B(3, 4); B b3 = b1 + b2; Console.WriteLine("b1 + b2 = (" + b3.X + ", " + b3.Y + ")"); } }

这段代码的输出结果是:

a1 + a2 = 3 b1 + b2 = (4, 6)

2、动态多态性

动态多态是指在运行时根据对象类型来确定调用哪个函数的多态性。例如,一个基类可以有一个虚函数,派生类可以重写这个虚函数,然后在运行时根据对象类型调用适当的函数。这种多态性是通过抽象类继承和虚函数实现的

2.1 抽象类/成员——abstract

在C#中,抽象类是一种特殊的类,它不能被实例化,而只能作为其他类的基类来使用。抽象类包含抽象成员,这些成员没有实现,需要由子类来实现。抽象类用于定义一组相关的类的通用行为和属性,而不是为特定的类实现具体的行为和属性。

定义抽象类时,需要在类名前面添加abstract关键字。抽象类中可以包含普通的方法、属性、字段等成员,也可以包含抽象成员,即没有实现的方法或属性。抽象成员需要在声明时使用abstract关键字,并且不能包含方法体(即方法的主体执行代码)。抽象类也可以继承自其他类或抽象类。不能创建一个抽象类的实例 ,不能在一个抽象类外部声明一个抽象方法。子类继承抽象类时,必须实现抽象类中的所有抽象成员。如果子类没有实现抽象成员,则子类也必须声明为抽象类。

以下是一个使用抽象类的示例:

// 定义抽象类 Shape abstract class Shape { public abstract double GetArea(); } // 定义矩形类 Rectangle,继承自 Shape class Rectangle : Shape { double length; double width; // 定义构造函数,传入矩形的长度和宽度 public Rectangle(double l, double w) { length = l; width = w; } // 实现抽象类 Shape 的抽象方法 GetArea(),计算矩形面积 public override double GetArea() { return length * width; } } // 定义三角形类 Triangle,继承自 Shape class Triangle : Shape { double bottom; double height; // 定义构造函数,传入三角形的底和高 public Triangle(double b, double h) { bottom = b; height = h; } // 实现抽象类 Shape 的抽象方法 GetArea(),计算三角形面积 public override double GetArea() { return 0.5 * bottom * height; } } // 程序入口类 Program class Program { static void Main(string[] args) { // 创建 Rectangle 实例 rect,传入矩形的长度和宽度 Shape rect = new Rectangle(5, 10); // 打印矩形面积 Console.WriteLine("矩形的面积为:" + rect.GetArea()); // 创建 Triangle 实例 tri,传入三角形的底和高 Shape tri = new Triangle(5, 10); // 打印三角形面积 Console.WriteLine("三角形的面积为:" + tri.GetArea()); } }

在上面的示例中,我们定义了一个抽象类Shape,其中包含一个抽象方法GetArea,用于计算图形的面积。

然后定义了两个子类Rectangle和Triangle,分别实现了GetArea方法。在Main方法中,分别使用这两个子类来计算图形的面积。由于Shape是抽象类,不能被实例化,因此使用子类来实例化Shape类的引用。

2.2 不可继承类/方法——sealed

补充一下,使用sealed关键字可以将一个类声明为不能被继承的,或将一个方法声明为不能被重写的。

sealed关键字只能用于类和方法,不能用于字段、属性或事件 。抽象类不能被声明为sealed! sealed class MyClass { // ... } 2.3 虚方法——virtual

在C#中,虚方法指的是在基类中定义的方法,可以被子类重写。在基类中使用virtual关键字来定义虚方法,而在子类中可以使用override关键字来重写虚方法。

抽象类是提炼出大家共用的方法但自己不实现也不能用,留给子类实现并使用。虚方法则不同,在基类中已经实现并可以使用该方法,同时还允许子类根据自己的需要重新实现(改写)基类中的方法。

例如,基类中可能有一个 Draw 方法,用于绘制某个图形,但是不同的子类可能需要绘制不同的图形,因此可以重写 Draw 方法,以便子类可以实现自己独特的绘制功能。下面是一个使用虚方法的示例代码:

using System; class Shape { public virtual void Draw() //定义虚方法 { Console.WriteLine("绘制一个图形"); } } class Rectangle : Shape { public override void Draw() //重写虚方法 { Console.WriteLine("绘制一个矩形"); } } class Circle : Shape { public override void Draw() //重写虚方法 { Console.WriteLine("绘制一个圆形"); } } class Program { static void Main(string[] args) { Shape shape = new Shape(); shape.Draw(); Shape rect = new Rectangle(); rect.Draw(); Shape circle = new Circle(); circle.Draw(); } }

在上面的代码中,Shape 类中定义了一个虚方法 Draw,子类 Rectangle 和 Circle 分别重写了这个方法,以便实现自己独特的绘制功能。在 Program 类中,我们创建了一个 Shape 对象、一个 Rectangle 对象和一个 Circle 对象,并且都调用了它们的 Draw 方法。由于 Rectangle 和 Circle 类都重写了 Draw 方法,因此它们的 Draw 方法输出的结果分别是“绘制一个矩形”和“绘制一个圆形”。

由此可以知道:

虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有