本文仅作学习笔记与交流,不作任何商业用途,作者能力有限,如有不足还请斧正

本系列旨在通过补全学习之后,给出任意类图都能实现并做到逻辑上严丝合缝

1.继承方法

C# & Unity 面向对象补全计划 之 继承(字段与属性)-CSDN博客

本文讲述继承方法与多态性,是继承的重要伴随知识

我想实现如下内如:

有一个Computer类和一个Mycomputer类作为子类

父类提供推荐配置,而子类提出我自己的配置,并打印

1.1构造函数继承

子类构造函数会默认先调用父类构造函数

举个栗子:

Computer类:

class Computer {
    // 公共字段
    public string cpu ;
    // 私有字段
    private string gpu ;
    // 公共属性
    public string gpu_name {
        get => gpu;
        set => gpu = value;
    }
    // 公共构造函数
    public Computer() {
        cpu = "7500f及以上";
        gpu_name = "Rx580及以上";
        Console.WriteLine("{0},{1}",cpu,gpu_name);
    }
    // 公共自定义方法
    public virtual void Configuration() {
       
    }
}

当我执行Computer类的对象时,会输出如下:

子类继承: 

也可以用base关键词进行父类构造函数调用,用的不多故不做演示

class MyComputer : Computer {

    public MyComputer() {

        cpu = "5600";
        gpu_name = "3060";
        Console.WriteLine("{0},{1}", cpu, gpu_name);
    }
}

子类对象:

 输出:

如果父类构造函数是私有的话,就无法使用子类构造函数了

Q:我可以在调用子类构造函数的时候,不调用父类构造函数吗?

A:不行,因为这是语言设计的一部分,用于确保父类的成员被正确初始化

1.2构造函数继承在Unity之中的不同点

如果你是没有继承mono的类 那么会符合正常的继承规则

  public void Start()
  {
      B b= new B();   
  }  
public class A{
      public A() {
          Debug.Log("A构造函数");
      }
  }
  public class B:A
      { public B() {
          Debug.Log("B构造函数");
      } 
  }

 但是,如果父类脚本继承了mono还要强行写一个显示构造函数 情况就会发生改变:

public class Father : MonoBehaviour
{
    public Father(){
        Debug.Log("父类存活 -- 构造函数");
    }
}
public class Son : Father
{
    public Son(){
        Debug.Log("子类存活--构造函数");
    }
}

来看看会发生什么:

 

这是因为

所以我在这里及不建议你继承mono的脚本还要写构造函数进行初始化字段和属性,应该使用mono下的生命周期函数----awake或者start来替代

下面的virtual是什么意思请跳转本篇标题3 --多态

 1.3方法继承

我将Computer类添加了一个自定义方法,并将输出语句放到方法里

class Computer {
    // 公共字段
    public string cpu ;
    // 私有字段
    private string gpu ;
    // 公共属性
    public string gpu_name {
        get => gpu;
        set => gpu = value;
    }
    // 公共构造函数
    public Computer() {
        cpu = "7500f及以上";
        gpu_name = "Rx580及以上";
        
    }
    // 公共自定义方法
    public  void Configuration() {
        Console.WriteLine("{0},{1}", cpu, gpu_name);
    }
}

如果子类继承以后,写一个相同名字的方法,会输出什么?

MyComputer mycomputer = new MyComputer();
mycomputer.Configuration();
class Computer {
    // 公共字段
    public string cpu ;
    // 私有字段
    private string gpu ;
    // 公共属性
    public string gpu_name {
        get => gpu;
        set => gpu = value;
    }
    // 公共构造函数
    public Computer() {
        cpu = "7500f及以上";
        gpu_name = "Rx580及以上";
        
    }
    // 公共自定义方法
    public  void Configuration() {
        Console.WriteLine("{0},{1}", cpu, gpu_name);
    }
}

class MyComputer : Computer {

    public MyComputer() {

        cpu = "5600";
        gpu_name = "3060";
      
    }
    public void Configuration()
        {
        Console.WriteLine("{0},{1}", cpu, gpu_name);
    }
}

不会继承,所以如果不做特殊处理的话,只会调用自己的方法

所以就用到了多态,直接跳到标题3:多态下

2.多态(上)

2.1方法重载

是指可以出现同名方法,规则如下:

public class Example
{
    public void Print(int a) { }
    public void Print(int a, int b) { }
    public void Print(double a) { }
    public void Print(int a, double b) { }
    public void Print(double a, int b) { }
}

2.2运算符重载 

运算符重载,一般也用的不多先用现学即可 

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

3.多态(下)

3.1虚方法

在C#中,虚方法(virtual method)是指在基类中声明并可以在派生类中重写的方法

虚方法使用 virtual 关键字进行声明:

 public virtual void Configuration() {
     Console.WriteLine("推荐配置为{0},{1}", cpu, gpu_name);
 }

子类可以使用override关键字进行重写,并且添加逻辑:

   public override void Configuration()
       {      
           Console.WriteLine("我的配置为{0},{1}", cpu, gpu_name);
           Console.WriteLine("打印完毕");
   }

调用:

Computer computer = new Computer();
computer.Configuration();
MyComputer mycomputer = new MyComputer();
mycomputer.Configuration();

结果:

        但是我们注意到了一点 我在调用的时候new了两个对象,如果我就想用一个子对象连同父类虚方法的一齐调用呢?

3.2关键词:Base

        这次我们在unity中来举例,因为继承mono的脚本是不能去new的(虽然new了只是报警告继续而不是报错终止)

        众所周知,Update函数是每一帧都去调用一次,所以我将其写做虚方法

public class Father : MonoBehaviour
{
    // Update is called once per frame
    public virtual void Update()
    {
        Debug.Log("父类一句话");
    }
}

         子类去继承并重写,看看没有加关键词会发生什么

public class Son : Father
{
    // Update is called once per frame
   public override void Update() {
        
        Debug.Log("子类的一句话");
    }
}

父类的update函数完全没有起作用!

再看子类中加了关键词Base呢?

public class Son : Father
{
    // Update is called once per frame
   public override void Update() {
        base.Update();
        Debug.Log("子类的一句话");
    }
}

 

3.3抽象方法

抽象方法没有方法体,只包含在抽象类之中,只有方法签名,它们必须在派生类中实现

举个栗子:电脑这一概念的确就符合抽象的概念

abstract class Computer {
    // 公共字段
    public string cpu ;
    // 私有字段
    private string gpu ;
    // 公共属性
    public string gpu_name {
        get => gpu;
        set => gpu = value;
    }
    // 公共构造函数
    public Computer() {
        cpu = "7500f及以上";
        gpu_name = "Rx580及以上";
        
    }
    // 公共自定义方法
    public abstract void Configuration();      
}

子类继承的话,则强制进行方法重写:

 public override void Configuration()
     {      
         Console.WriteLine("我的配置为{0},{1}", cpu, gpu_name);
         Console.WriteLine("打印完毕");
 }

二者区别

Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐