【学习资料】

  《C#图解教程》(第4~7章):https://www.cnblogs.com/moonache/p/7687551.html
  电子书下载:https://pan.baidu.com/s/1mhOmBG0

【内容】

    • 所有类的基类
    • 类的组成
    • 类的实例化、内存分配
    • 类的特性:封装、继承、多态
    • 接口
    • 扩展知识
      • 隐藏基类的成员
      • struct、class
      • 抽象函数(abstract)、虚函数(virtual)
      • 抽象类(abstract)、接口(interface)

【笔记】

  所有类的基类: object 

  类由2部分组成

    > 数据成员:存储与类或类的实例相关的数据
    > 函数成员:执行代码

      

  类的实例化

    > 声明一个类的引用,指向空数据null

      

    > new数据部分,并将引用指向数据

      


【类的特性】

  类的三大特性:封装、继承、多态

    > 封装

      > 访问修饰符

    > 继承

      > 派生子类

      > 构造/析构函数

    > 多态

      > 静态多态性:函数重载(不同参数)、运算符重载

      > 动态多态性:虚函数、抽象函数、隐藏方法

  • 封装

    

  • 继承

    • this   当前类对象
    • base : 父类对象
    • sealed密封类,不能被继承
    • sealed class Entity
      {
      }
      class Car : Entity // sealed不能被继承,会报错
      {
      }
    • C#不支持类的多继承,但可以继承多个接口(interface)
    • 父类初始化:在初始化列表里进行
    • public Tabletop(double l, double w) : base(l, w)
      { }
    • 构造函数
      • 在创建类对象时,会执行构造函数:Car car = new Car()
      • 构造顺序:先调用父类的构造,再调用子类的
    • 析构函数
      • 在释放对象时(GC垃圾回收),会执行析构函数
      • 析构顺序:先调用子类的析构,再调用父类的
    • class Entity
      {
      // 默认构造函数,无参数
      public Entity()
      {
      Debug.Log("new Entity");
      }
      // 带参构造函数
      public Entity(int id)
      {
      Debug.Log("new Entity id=" + id);
      }
      // 重写析构函数,一个类只能有一个,且无参数
      ~Entity()
      {
      Debug.Log("delete Entity");
      }
      }
      class Car : Entity // sealed不能被继承,会报错
      {
      // 不写父类的构造,默认调用默认构造函数Entity()
      public Car()
      {
      Debug.Log("new Car");
      }
      // 在初始化列表: 调用父类的带参构造函数
      public Car(int id)
      : base(id)
      {
      Debug.Log("new Car");
      }
      // 重写析构函数,一个类只能有一个,且无参数
      ~Car()
      {
      Debug.Log("delete Car");
      }
      }
  • 多态
    • 静态多态性

      • 函数重载(不同参数)

      • public Tabletop(double l, double w) : base(l, w)
        { }
      • 运算符重载
      • public static Box operator +(Box b, Box c)
        { }
    • 动态多态性:子类重写父类方法

      • 虚函数

        • 关键字:virtual /  override
        • 子类重写虚函数后:不管在父类中调用,还是在子类中调用,执行的都是子类重写后的函数 (Car.Move)
        • 调用父类虚函数的方法:通过 base 关键字调用(base.Move())
        • 注:子类也可不重写父类的虚函数
        • class Entity
          {
          public void AI()
          {
          Move();
          }
          public virtual void Move() // 虚函数声明 virtual
          {
          Debug.Log("Entity.Move");
          }
          }
          class Car : Entity
          {
          // 重写方法
          public override void Move() // 重写虚函数 override
          {
          Debug.Log("Car.Move");
          }
          } // 测试Test
          void Start()
          {
          Entity entity = new Car();
          Car car = (Car)entity;
          entity.Move(); // 输出:Car.Move
          car.AI(); // 输出:Car.Move
          }
      •  抽象函数

        • 关键字:abstract / override
        • 注:父类只声明抽象函数,没有具体实现
        • 注:存在抽象函数的类,必须声明为抽象类,且不能实例化成对象
        • // 含有抽象函数,必须声明为抽象类,且不能实例化对象
          abstract class Entity
          {
          public abstract void Move(); // 抽象函数
          }
          class Car : Entity
          {
          // 子类必须实现父类的抽象函数
          public override void Move()
          {
          Debug.Log("Car.Move");
          }
          } void Start()
          {
          // 报错,抽象类无法实例化
          //Entity entity2 = new Entity(); Car entity = new Car();
          entity.Move(); // 输出:Car.Move
          }
      • 隐藏方法 (不推荐,容易出错)

        • 子类重写父类虚函数时,不写 override 关键字,编译器也会显示警告(warning)
        • 注:具体执行父类/子类函数,根据调用环境决定(指向对象的引用类型、父类or子类其他函数中进行调用)
        • 测试1:不同引用类型调用Move 、通过AI()函数中调用
          • class Entity
            {
            public void AI()
            {
            Move();
            }
            public virtual void Move()
            {
            Debug.Log("Entity.Move");
            }
            }
            class Car : Entity
            {
            // 不写override
            public void Move()
            {
            Debug.Log("Car.Move");
            }
            } void Start()
            {
            Entity entity = new Car();
            Car car = (Car)entity;
            entity.Move(); // 输出:Entity.Move
            entity.AI(); // 输出:Entity.Move
            car.Move(); // 输出:Car.Move
            car.AI(); // 输出:Entity.Move
            }
        •  测试2:子类重写AI()函数
          • class Entity
            {
            public virtual void AI()
            {
            Move();
            }
            public virtual void Move()
            {
            Debug.Log("Entity.Move");
            }
            }
            class Car : Entity
            {
            public override void AI()
            {
            Move();
            }
            // 不写override
            public void Move()
            {
            Debug.Log("Car.Move");
            }
            } void Start()
            {
            Entity entity = new Car();
            Car car = (Car)entity;
            entity.Move(); // 输出:Entity.Move
            entity.AI(); // 输出:Car.Move
            car.Move(); // 输出:Car.Move
            car.AI(); // 输出:Car.Move
            }

【接口】 

  > 关键字:interface

  > 相当于是个规则,里面只能有:方法、属性、索引、事件

  > 一个类只能继承一个父类,但可以实现多个接口 

  > 注:接口 也可以 继承另一个 接口

  > 注:一个类继承了接口后,接口中所有的方法(包括属性、索引、事件)都必须实现

  > 注:实现接口中的方法必须定义为 public

    interface EntityInterface
{
int Value { get; set; } // 可以声明属性,但子类中必须实现
void Move(); // 不用写修饰符(public) //int value; // 不能定义变量
//void AI() { Move(); } // 不能实现接口函数
}
class Car : EntityInterface
{
// 必须实现接口中的属性,且必须为 public
public int Value
{
get;
set;
}
// 必须实现接口中的函数,且必须为 public
public void Move()
{
}
}

【扩展知识】

  • 隐藏基类的成员

    • 子类通过new关键字,隐藏父类的成员数据、方法
    • 具体调用的是哪个?根据调用环境决定(指向对象的引用类型、父类or子类其他函数中进行调用)

        

    • 案例1:不同引用类型获取.value、调用父类的PrintValue

      • class A
        {
        public int value = ;
        public void PrintValue()
        {
        Debug.Log("A.value=" + value);
        }
        }
        class B : A
        {
        public new int value = ;
        }
        void Start()
        {
        A a = new B();
        B b = (B)a;
        Debug.Log(a.value); // 1
        Debug.Log(b.value); // 2
        a.PrintValue(); // A.value=1
        b.PrintValue(); // A.value=1
        }
    • 案例2:子类隐藏父类的PrintValue
      • class A
        {
        public int value = ;
        public void PrintValue()
        {
        Debug.Log("A.value=" + value);
        }
        }
        class B : A
        {
        public new int value = ;
        // 隐藏父类函数
        public new void PrintValue()
        {
        Debug.Log("B.value=" + value);
        }
        }
        void Start()
        {
        A a = new B();
        B b = (B)a;
        a.PrintValue(); // A.value=1
        b.PrintValue(); // B.value=2
        }
    • 案例3:子类重写父类的PrintValue
      • class A
        {
        public int value = ;
        public virtual void PrintValue()
        {
        Debug.Log("A.value=" + value);
        }
        }
        class B : A
        {
        public new int value = ;
        // 重写父类函数
        public override void PrintValue()
        {
        Debug.Log("B.value=" + value);
        }
        }
        void Start()
        {
        A a = new B();
        B b = (B)a;
        a.PrintValue(); // B.value=2
        b.PrintValue(); // B.value=2
  • struct 、class

    • 类 是 引用类型,结构体 是 值类型

    • 因此结构体不能=null,也不需要使用new

    • 结构体 不支持继承

    • 结构体 不能声明 默认(无参)构造函数,不能声明 析构函数

    • 结构体成员 不能指定为 abstract、virtual 或 protected

 

  • 抽象函数(abstract) 、虚函数(virtual)

    • abstract:父类只声明没有具体实现,子类必须重写实现父类中的抽象函数

    • virtual:子类可以不重写父类的虚函数

 

  • 抽象类(abstract) 、接口(interface)

    • 抽象类:依然是一个类,不能被实例化,它仍然包含类的函数

    • 接口:相当于是个规则,里面只能有方法、属性、索引、事件

    • 抽象类:有抽象的方法,也有不抽象的方法。子类必须实现父类的抽象方法

    • 接口:继承了接口后,所有的接口方法都必须实现

    • 一个类只能继承一个父类,但是可以实现多个接口

【Unity|C#】基础篇(3)——类(class)/ 接口(interface)的更多相关文章

  1. 新年在家学java之基础篇-高级类的特性

    继承 extends 子类的共性代码都是继承自父类的,每个子类只要写自己特有的代码 class 子类 extends 父类 继承提高了代码的复用性,提供了多态的前提,但是不要为了某个功能去继承 子类不 ...

  2. 线程基础知识01-Thread类,Runnable接口

    常见面试题:创建一个线程的常用方法有哪些?Thread创建线程和Runnable创建线程有什么区别? 答案通常集中在,继承类和实现接口的差别上面: 如果深入问一些问题:1.要执行的任务写在run()方 ...

  3. C#基础篇七类和静态成员

    1.new关键字做的4个事情 1.1 开辟堆空间 a.开辟多大的空间呢? 当前类 所有的 成员变量类型所占空间的总和 + 类型指针(方法表的地址) b.开辟了空间干什么用呢? 存放 成员变量 1.2 ...

  4. JAVA基础篇 之 类的初始化

    类中属性的隐式初始化,代码如下,我们看下不同类型默认的初始值是什么 创建一个Demo类如下: class Demo { int a; byte b; short c; long d; boolean ...

  5. 【Java_多线程并发编程】基础篇—Thread类中start()和run()方法的区别

    1. start() 和 run()的区别说明 start()方法: 它会启动一个新线程,并将其添加到线程池中,待其获得CPU资源时会执行run()方法,start()不能被重复调用. run()方法 ...

  6. C# 类(9) - 接口 Interface

    Interface 接口 类似 抽象类,也不能被实例化...(前面说的静态类,加上抽象类,还有这个,都3个了)接口其实比 抽象类 更加抽象.接口的方法(这个方法还不能有实体代码,和抽象类的抽象方法差不 ...

  7. 图解Python 【第五篇】:面向对象-类-初级基础篇

    由于类的内容比较多,分为类-初级基础篇和类-进阶篇 类的内容总览图: 本节主要讲基础和面向对象的特性 本节内容一览图: 前言总结介绍: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 ...

  8. cocos2dx基础篇(3) 常用重要类

    ---------------------------------------- 入口类main.cpp 主要控制类AppDelegate.cpp -------------------------- ...

  9. Hibernate.基础篇《一》.Hibernate工具类.

    Hibernate.基础篇<一>.Hibernate工具类. 话述: Hibernate.基础篇第一篇,前面是代码.后面再加理论&实践. Hibernate使用的版本是:5.x,在 ...

随机推荐

  1. 对于搭建网站中出现“You don't have permission to access this resource.”错误提示的解决思路

    我是用的是树莓派搭载了ubuntu系统 配置php+apache的网站环境,但在登陆网站进行网站初始化设置时出现错误提示,其大意是没有访问权限,上网搜索了一系列相关教程,都说明对apache2.con ...

  2. 数据结构(集合)学习之Set

    集合 框架关系图: Collection接口下面有三个子接口:List.Set.Queue.此篇是关于Set<E>的简单学习总结. 补充:HashTable父类是Dictionary,不是 ...

  3. Linux 下安装 java

    yum 安装java 配置环境 /etc/profile export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7. ...

  4. c++编程之内存模型

    我们在编程的时候,无可避免要申明变量,在这个变量可以是在()中,可以在{}中,也可以直接在外面,也可以用new的方式.那么当我们在申明变量的时候,实质上我们所做的工作是:关联了一个内存模型! 上代码: ...

  5. 字符串相等 impossible 1480

    题目描述 两个长度不超过80的字符串,串中包括大写.小写和空格字符,去掉空格并忽略大小写后,判断两个字符串是否相等. 输入描述 第1行输入是测试数据的组数n,每组测试数据占两行,第1行是第一个字符串s ...

  6. ng-指令

    在 Angular 中最常用的指令分为两种,它们分别是 属性型指令 和 结构型指令. NgClass 作用:添加或移除一组 CSS 类 NgStyle 作用:添加或移除一组 CSS 样式 NgMode ...

  7. VMware桥接模式下虚拟机ping主机不通

    现象: VMware设置为桥接模式,虚拟机ping主机不通,主机ping虚拟机通. 解决: 尝试以下几种方法 关闭主机(专用网络.来宾或公用网络)和虚拟机的防火墙. 更改桥接的物理网卡,确保是主机正在 ...

  8. 剑指offer-面试题18-删除链表中重复的节点-链表

    /* 题目: 删除链表中重复的节点 */ /* 思路: 1.声明一个头节点head,即使首元节点被删除,也可返回head->next 2.声明两个指针, 一个指针qNode指向确定不会删除的链表 ...

  9. PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) (排序)

    At the beginning of every day, the first person who signs in the computer room will unlock the door, ...

  10. jquery赋值

    $("#test1").text("Hello world!"); $("#test2").html("<b>Hell ...