彩妆做推广的网站,怀化找工作网站,wordpress邮件有%3c%3e,宜春seo网站推广目录
C# 多态性
静态多态性
函数重载
运算符重载
动态多态性
virtual 和 abstract
抽象方法和虚方法的区别
重载(overload)和重写(override)
隐藏方法 C# 多态性
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性意味着有多重形式。在面向对象编程范式中…目录
C# 多态性
静态多态性
函数重载
运算符重载
动态多态性
virtual 和 abstract
抽象方法和虚方法的区别
重载(overload)和重写(override)
隐藏方法 C# 多态性
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性意味着有多重形式。在面向对象编程范式中多态性往往表现为一个接口多个功能。
多态性可以是静态的或动态的。在静态多态性中函数的响应是在编译时发生的。在动态多态性中函数的响应是在运行时发生的。
在 C# 中每个类型都是多态的因为包括用户定义类型在内的所有类型都继承自 Object。
多态就是同一个接口使用不同的实例而执行不同操作如图所示 现实中比如我们按下 F1 键这个动作 如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档如果当前在 Word 下弹出的就是 Word 帮助在 Windows 下弹出的就是 Windows 帮助和支持。 同一个事件发生在不同的对象上会产生不同的结果。 静态多态性
在编译时函数和对象的连接机制被称为早期绑定也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为
函数重载
在C#中函数重载指的是在同一个类中可以定义多个具有相同名称但参数列表不同的函数。通过函数重载可以根据不同的参数列表来调用合适的函数。
下面是一个简单的示例演示了如何在C#中使用函数重载
using System;public class DateUtils
{// 函数重载public string FormatDate(DateTime dt){return dt.ToString(yyyy/MM/dd HH:mm:ss.fff);}public string FormatDate(DateTime dt, string format){return dt.ToString(format);}
}public class Program
{public static void Main(){DateUtils utils new DateUtils();DateTime now DateTime.Now;// 使用不同的重载函数进行日期格式化string formattedDate1 utils.FormatDate(now); // 使用第一个重载函数string formattedDate2 utils.FormatDate(now, yyyy-MM-dd HH:mm:ss); // 使用第二个重载函数// 输出格式化后的日期Console.WriteLine(格式化日期1: formattedDate1);Console.WriteLine(格式化日期2: formattedDate2);}
}在上面的示例中DateUtils 类中定义了两个名为 FormatDate 的函数。第一个函数接受一个 DateTime 类型的参数并将日期格式化为特定的格式。第二个函数接受一个 DateTime 类型的参数和一个表示日期格式的字符串参数并根据传入的格式对日期进行格式化。这两个函数拥有相同的名称但参数列表不同。
运算符重载
C#允许我们重定义或重载内置运算符以便在用户自定义类型上使用它们。运算符重载通过关键字operator后面跟着运算符的符号来定义。
下面是一些常见的运算符重载的示例
1、算术运算符
重载为public static T operator (T operand1, T operand2)-重载为public static T operator -(T operand1, T operand2)*重载为public static T operator *(T operand1, T operand2)/重载为public static T operator /(T operand1, T operand2)%重载为public static T operator %(T operand1, T operand2)
2、比较运算符
重载为public static bool operator (T operand1, T operand2)!重载为public static bool operator !(T operand1, T operand2)重载为public static bool operator (T operand1, T operand2)重载为public static bool operator (T operand1, T operand2)重载为public static bool operator (T operand1, T operand2)重载为public static bool operator (T operand1, T operand2)
3、逻辑运算符
!重载为public static bool operator !(T operand)重载为public static bool operator (T operand1, T operand2)|重载为public static bool operator |(T operand1, T operand2)
4、位运算符
~重载为public static T operator ~(T operand)重载为public static T operator (T operand1, T operand2)|重载为public static T operator |(T operand1, T operand2)^重载为public static T operator ^(T operand1, T operand2)
5、赋值运算符
重载为public static void operator (T destination, T source)重载为public static T operator (T operand1, T operand2)-重载为public static T operator -(T operand1, T operand2)*重载为public static T operator *(T operand1, T operand2)/重载为public static T operator /(T operand1, T operand2)%重载为public static T operator %(T operand1, T operand2)
这些示例只是一些常见的运算符重载示例你可以根据自己的需求重载其他运算符。需要注意的是并非所有运算符都可以被重载具体可重载的运算符列表请参考C#官方文档。
代码示例
using System;public class Complex
{public double Real { get; set; }public double Imaginary { get; set; }public Complex(double real, double imaginary){Real real;Imaginary imaginary;}// 重载加法运算符 public static Complex operator (Complex c1, Complex c2){return new Complex(c1.Real c2.Real, c1.Imaginary c2.Imaginary);}// 重载减法运算符 -public static Complex operator -(Complex c1, Complex c2){return new Complex(c1.Real - c2.Real, c1.Imaginary - c2.Imaginary);}// 重载乘法运算符 *public static Complex operator *(Complex c1, Complex c2){double real c1.Real * c2.Real - c1.Imaginary * c2.Imaginary;double imaginary c1.Real * c2.Imaginary c1.Imaginary * c2.Real;return new Complex(real, imaginary);}// 重载复数的输出格式public override string ToString(){return ${Real} {Imaginary}i;}
}class Program
{static void Main(){Complex c1 new Complex(1, 2);Complex c2 new Complex(3, 4);Complex sum c1 c2; // 使用重载的加法运算符Console.WriteLine($总和: {sum});Complex difference c1 - c2; // 使用重载的减法运算符Console.WriteLine($差别: {difference});Complex product c1 * c2; // 使用重载的乘法运算符Console.WriteLine($相乘: {product});}
}当上面的代码被编译和执行时它会产生下列结果
总和: 4 6i
差别: -2 -2i
相乘: -5 10i
动态多态性
在C#中使用抽象类和虚方法可以实现动态多态性。
C# 允许您使用关键字 abstract 创建抽象类用于提供接口的部分类的实现。当一个派生类继承自该抽象类时实现即完成。抽象类包含抽象方法抽象方法可被派生类实现。派生类具有更专业的功能。
请注意下面是有关抽象类的一些规则
抽象类不能被实例化只能被用作其他类的基类。抽象类中可以包含抽象方法这些方法没有具体的实现而是由派生类来实现。通过在类定义前面放置关键字 sealed可以将类声明为密封类。当一个类被声明为 sealed 时它不能被继承。抽象类不能被声明为 sealed。
下面的程序演示了一个抽象类
using System;// 定义抽象类
public abstract class Shape
{public string Name { get; set; }// 定义抽象方法public abstract double CalculateArea();
}// 继承自抽象类的具体类圆形
public class Circle : Shape
{public double Radius { get; set; }// 实现抽象方法public override double CalculateArea(){return Math.PI * Radius * Radius;}
}// 继承自抽象类的具体类正方形
public class Square : Shape
{public double SideLength { get; set; }// 实现抽象方法public override double CalculateArea(){return SideLength * SideLength;}
}class Program
{static void Main(){Circle circle new Circle { Name 圆形, Radius 3 };Console.WriteLine(圆形的面积 circle.CalculateArea()); // 输出结果圆形的面积 28.274333882308138Square square new Square { Name 正方形, SideLength 4 };Console.WriteLine(正方形的面积: square.CalculateArea()); // 输出结果正方形的面积: 16}
}另外虚方法是在基类中可以使用关键字virtual来声明一个方法为虚方法表示它可以被派生类重写。而在派生类中可以使用关键字override来重写基类中的虚方法。
通过使用抽象类和虚方法可以实现代码的可扩展性和灵活性。抽象类提供了一种统一的接口定义了需要实现的方法而具体的实现则由派生类来完成。虚方法允许在派生类中重写方法实现不同的行为。
以下是一个简单的代码示例演示了如何使用抽象类和虚方法来实现动态多态性。
using System;// 定义一个抽象类
public abstract class Shape
{// 定义一个虚方法public virtual double CalculateArea(){return 0;}
}// 派生类1矩形
public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }// 实现抽象方法public override double CalculateArea(){return Width * Height;}
}// 派生类2圆形
public class Circle : Shape
{public double Radius { get; set; }// 实现抽象方法public override double CalculateArea(){return Math.PI * Radius * Radius;}
}class Program
{static void Main(){// 创建一个矩形对象Shape rect new Rectangle { Width 5, Height 10 };Console.WriteLine(矩形的面积 rect.CalculateArea());// 创建一个圆形对象Shape circle new Circle { Radius 3 };Console.WriteLine(圆形的面积 circle.CalculateArea());}
}当上面的代码被编译和执行时它会产生下列结果
矩形的面积50
圆形的面积28.274333882308138
virtual 和 abstract
virtual关键字用于修饰方法表示该方法在基类中有一个默认实现但派生类可以选择性地重写它。通常情况下virtual方法会提供一个默认实现但可以在派生类中进行修改或扩展。即使派生类没有重写virtual方法它仍然会使用基类中的默认实现。abstract关键字用于修饰方法或类表示它们没有具体的实现。抽象方法只有定义没有实现派生类必须重写它们并且提供具体的实现。抽象类本身也不能被实例化只能作为基类被其他类继承。
需要注意的是抽象方法只能存在于抽象类中而不是普通的类。如果一个类包含抽象方法则该类本身必须被声明为抽象类。而虚方法可以存在于任何类中无论是抽象类还是普通类。
总之virtual和abstract关键字都用于实现多态性在派生类中重新定义父类的方法。virtual方法允许派生类选择重写并提供新的实现而abstract方法则要求派生类必须提供具体的实现。另外抽象类本身不能被实例化只能作为其他类的基类使用。
抽象方法和虚方法的区别
抽象方法abstract method必须在抽象类中声明并且没有具体的实现部分。派生类必须重写并提供具体的实现否则派生类将无法被实例化。虚方法virtual method在基类中有一个默认的实现但也可以在派生类中进行重写。派生类可以选择性地覆盖虚方法或者直接使用基类的默认实现。抽象方法和虚方法都可以供派生类重写以定制化行为但抽象方法必须在派生类中进行重写而虚方法可以选择性地进行重写。
重载(overload)和重写(override)
1、重载(overload): 在同一个作用域(一般指一个类)的两个或多个方法函数名相同参数列表不同的方法叫做重载它们有三个特点(俗称两必须一可以): 方法名必须相同 参数列表必须不相同 返回值类型可以不相同
2、重写(override):子类中为满足自己的需要来重复定义某个方法的不同实现需要用 override 关键字被重写的方法必须是虚方法用的是 virtual 关键字。它的特点是(三个相同):
相同的方法名相同的参数列表相同的返回值
代码示例
using System;public class Calculator
{// 方法重载参数列表不同public int Add(int num1, int num2){return num1 num2;}public double Add(double num1, double num2){return num1 num2;}
}public class Shape
{// 虚方法public virtual void Draw(){Console.WriteLine(正在绘制形状。。。);}
}public class Circle : Shape
{// 重写基类的虚方法public override void Draw(){Console.WriteLine(正在绘制圆。。。);}
}class Program
{static void Main(){Calculator calculator new Calculator();int result1 calculator.Add(3, 4); // 调用第一个Add方法double result2 calculator.Add(2.5, 3.7); // 调用第二个Add方法Console.WriteLine(int加法的结果 result1); // 输出结果int加法的结果 7Console.WriteLine(double加法的结果: result2); // 输出结果double加法的结果: 6.2Shape shape1 new Shape();shape1.Draw(); // 输出结果正在绘制形状。。。Shape shape2 new Circle();shape2.Draw(); // 输出结果正在绘制圆。。。}
}隐藏方法
当在派生类中定义一个与基类中同名的方法时会发生方法隐藏。使用关键字 new 可以实现方法隐藏。
using System;public class Shape
{public void Draw(){Console.WriteLine(正在绘制形状。。。);}
}public class Circle : Shape
{public new void Draw(){Console.WriteLine(正在绘制圆。。。);}
}class Program
{static void Main(){Shape shape1 new Shape();shape1.Draw(); // 输出结果正在绘制形状。。。Shape shape2 new Circle();shape2.Draw(); // 输出结果正在绘制形状。。。调用的是基类的方法Circle circle new Circle();circle.Draw(); // 输出结果正在绘制圆。。。}
}在上述代码中Shape 类定义了一个 Draw() 方法Circle 类继承自 Shape 并定义了一个同名的 Draw() 方法并使用 new 关键字进行方法隐藏。
在 Main() 方法中首先创建了一个 Shape 对象 shape1调用其 Draw() 方法输出结果为 正在绘制形状。。。。接着创建了一个 Circle 对象 shape2将其赋值给 Shape 类型的变量 shape2再次调用 shape2.Draw() 方法输出结果仍然为 正在绘制形状。。。这是因为变量的静态类型是 Shape所以调用的是基类的方法。最后创建了一个 Circle 对象 circle直接调用其 Draw() 方法输出结果为 正在绘制圆。。。这是因为直接通过派生类的实例调用方法时会调用派生类中隐藏的方法。
需要注意的是方法隐藏并不是方法重写。如果想要实现方法的多态性应该使用方法重写override而不是隐藏new。