首页 > C# > C#中类的继承和多态
2021
08-30

C#中类的继承和多态

C#中类的继承

继承是面向对象程序设计中最重要的概念之一。

继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易。同时也有利于重用代码和节省开发时间。

已有的类被称为的基类,这个新的类被称为派生类

class <派生类> : <基类>
{
 ...
}

在类定义前面放置关键字sealed,可以将类声明为密封类,该类将不能被继承

C#不支持多重继承,但是,可以使用接口来实现多重继承

现在有一个MyClass类和IMyInterFace接口,那么派生类可以直接继承
class DiyClass : MycLASS,iMyInterFace{}
用逗号隔开实现类似多重继承

基类的初始化

派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。

可以在成员初始化列表中进行父类的初始化。

class Mycalss1{
  public Mycalss1(double l, double w){
     length = l;
     width = w;
  }
}

class Mycalss2{
    public Mycalss2(double l, double w) : base(l, w)
    { }
}

使用base表示基类,base(l, w)表示隐式的创建基类实例对象

C#中类的多态

多态是同一个行为具有多个不同表现形式或形态的能力。

在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。

多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

在C#中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自Object

多态就是同一个接口,使用不同的实例而执行不同操作

静态多态性

在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。

C#提供了两种技术来实现静态多态性。分别为:函数重载和运算符重载

函数重载

可以在同一个范围内对相同的函数名有多个定义。

函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。

不能重载只有返回类型不同的函数声明。

下面的实例演示了两个相同的函数 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();
            Console.WriteLine("add1 :" + dataClass.Add(1, 2));
            Console.WriteLine("add2 :" + Add(1, 2, 3));
            Console.ReadKey();
        }
    }
}

运算符重载

重定义或重载C#中内置的运算符。

重载运算符是具有特殊名称的函数,是通过关键字operator后跟运算符的符号来定义的。

与其他函数一样,重载运算符有返回类型和参数列表

+、-、!、~、++、--:这些一元运算符只有一个操作数,且可以被重载
+、-、*、/、%:这些二元运算符带有两个操作数,且可以被重载
==、!=、<、>、<=、>=:这些比较运算符可以被重载
&&、||:这些条件逻辑运算符不能被直接重载
+=、-=、*=、/=、%=:这些赋值运算符不能被重载
=、.、?:、->、new、is、sizeof、typeof:这些运算符不能被重载
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();
         Box Box2 = new Box();
         Box Box3 = new 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);

         Console.WriteLine("Box1 的体积: {0}", Box1.getVolume());

         Console.WriteLine("Box2 的体积: {0}", Box2.getVolume());
         // 把两个对象相加
         Box3 = Box1 + Box2;
         Console.WriteLine("Box3 的体积: {0}", Box3.getVolume());
         Console.ReadKey();
      }
   }
}

动态多态性:

C#中的虚方法

当调用一个对象的方法时,系统会直接去检查这个对象申明定义的类,看所调用的方法是否为虚方法;

如果不是虚方法,那么它就直接执行该方法。而如果是一个虚方法,那么这个时候它就不会立刻执行该方法了,而是转去检查对象的实例类。

在这个实例类里,会检查这个实例类的定义中是否有重新实现该虚方法(通过override关键字),如果是有,那么OK,它就不会再找了,而马上执行该实例类中的这个重新实现的方法。而如果没有的话,系统就会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚方法的父类为止,然后执行该父类里重载后的方法

虚方法是使用关键字virtual声明的

public virtual int seth(int helght){ //实现代码 }

在派生类中使用关键字override进行修改
public override int seth(int helght){ //修改后的代码 }

虚方法可以在不同的继承类中有不同的实现

对虚方法的调用是在运行时发生的

c#中的抽象类

C#允许使用关键字abstract创建抽象类和抽象方法

抽象类不能被实例化,它们只提供部分实现,抽象类只能通过接口和作为其它类的基类使用

抽象类不能被声明为sealed

抽象方法是一个没有方法体的方法

abstract public int len();

在派生类中使用关键字override进行实现

public override int len(){ //实现代码 }

一个抽象类可以包含抽象和非抽象方法,当一个类继承于抽象类,那么这个派生类必须实现所有的的基类抽象方法

通过声明派生类也为抽象,我们可以避免所有或特定的虚方法的实现,这就是抽象类的部分实现

一个抽象类能够继承另一个非抽象类,继承了基类的方法,添加新的抽象和非抽象方法

C#中的接口

接口本身并不实现任何功能,它只是和声明实现该接口的对象订立一个必须实现哪些行为的契约。

接口只包含了成员的声明,成员的定义是派生类的责任

接口使得实现接口的类或结构在形式上保持一致

抽象类在某种程度上与接口类似,但是,抽象类大多只是用在当只有少数方法由基类声明由派生类实现时

使用interface关键字声明接口,接口声明默认是public的

interface IMyInterface{
    int Myfunc(int x , int y);
}

class MyClass:IMyInterFace{
    public int Myfunc(int x , int y){
        return x+y;
    }
}

以上代码定义了接口IMyInterface
通常接口命令以I字母开头
类MyClass继承了接口IMyInterFace并实现了Myfunc方法

接口的注意事项:

1、接口不能包含属性
2、接口中的方法不能包含方法体
3、接口中的方法声明时不能使用访问修饰符
4、继承接口的类(包括抽象类)必须将接口中的方法全部实现
5、接口可以继承接口,派生的接口无需实现方法
最后编辑:
作者:qingheluo
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。