天天看点

C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

一.构造方法

当创建一个类时, 系统会自动创建一个默认的无参构造方法, 这个方法和类同名, 在创建对象的时候自动调用. 默认的构造方法里面什么也没有, 重写之后就可以在创建对象的时候同时搞点事情了.

构造方法主要负责对类里面的字段进行初始化。

1.1 格式:
public 
           
1.2 注意事项:
  1. 构造方法必须要和类名重名;
  2. 构造方法没有返回值并且不加void, 但是可以有参数;
  3. 构造方法可以有多个重载;
  4. 构造方法只能在创建对象的时候才可以调用, 不能手动调用;
  5. 如果有带参数的构造方法, 想要调用默认构造必须显式的写出来;

二.析构方法

2.1 使用:

对象销毁之前都会自动调用析构方法

形象的来说, 我们玩游戏的时候把boss打死之后, boss会爆出各种装备金币,蓝啊之类的, 这些方法我们就可以在析构方法里面写;

2.2 语法:
~
           
2.3 注意:
  1. 只有类才有析构方法, 一个类只能有一个析构方法.
  2. 无法继承和重载析构方法;
  3. 不能手动调用, 对象在被销毁之前会自动调用;
  4. 析构方法没有访问修饰符, 没有参数;
  5. 必须和类名同名;

三.继承

3.1 概念:

继承用于创建可重用、扩展和修改在其他类中定义的行为的新类。 其成员被继承的类称为“基类”,继承这些成员的类称为“派生类”。 派生类只能有一个直接基类(C#中))。 但是,继承是可传递的。 如果 ClassB 派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员。

3.2 格式:
class 
           

学过构造方法之后, 就想给每个类都写个构造方法,以便简化初始化操作. 但是尝试过后发现如果父类写了带参数的构造方法, 子类就会报错了, 如何解决? base带你飞.

3.3 继承父类的构造方法:

孩子在创建对象的时候, 会先调用父类的构造方法, 如果父类是无参的就没有影响, 但是如果父类有有参数的构造方法, 孩子就需要传参数. 调用父类有参的构造方法有两个方法:

  1. 在父类中显式的将默认构造写出来;
  2. 子类在重写构造方法的时候利用 base关键字 传入父类的参数;
// 父类有参的构造方法
           
3.4 注意:
  1. 继承具有单向性, a -> b , b不能继承a;
  2. C#中,只能继承一个父类但是可以多重继承;
  3. 父类也叫基类, 子类也叫派生类;
  4. 继承具有传递性; a -> b, b -> c a就具有了c和b所有属性和方法;
  5. 基类有的,派生类都有;派生类有的,基类可能没有。即:派生类可以赋值给基类,而基类不能赋值给派生类。

子类在继承的时候不管想不想都会继承父类的所有字段和方法, 那么如果子类想用同样的方法搞特殊呢? 那就要引入多态了.

四.多态

栗子: 就拿我们创建的僵尸们来说, 僵尸都会攻击, 但是普通僵尸(小口咬), 路障僵尸(大口咬)和铁桶僵尸(超大口咬)的攻击方法不同, 这就是多态;

4.1重写父类方法的多态:
1.在访问修饰后面加上new关键字后重写:
// 父类的Attack方法
           

那么问题来了, 我虽然重写了父类的Attack方法, 但是我在某个地方还是想要使用父类的Attack方法的时候怎么办呢?

加上 base关键字 :
// 子类中
           
C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

结果

小结base:
  1. 调用基类被派生类重写的方法;
  2. 指定调用基类中某一个指定的构造方法;
4.2 virtual override 的多态

用这种方法来实现多态需要做两件事情:

1> 将父类中要实现多态性的方法改成虚方法, 即在返回值类型前加关键字 virtual:
// 僵尸父类
           
2>子类重写父类的方法, 即将方法隐藏的关键字 new 改为 override.
// 路障僵尸子类
           
C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

多态的运行结果

假如说现在有20个路障僵尸和10个铁桶僵尸, 他们现在都要进行攻击怎么实现? 借助数组呗. 那么问题又来了, 数组类型是什么? 数组中既有路障僵尸类又有铁桶僵尸类, 那想着能不能定义成他们的父类普通僵尸类呢? 要解决这个问题就需要用到里氏转换了.

4.3里氏转换
里氏转换的本质其实就是将父类强制转换成子类.
4.3.1 里氏转换第一原则
子类对象可以直接赋值给父类对象
// Main函数中
           
4.3.2 里氏转换第二原则
父类可以通过强制转换的方式转换成子类, 此时就可以调用子类中的成员了
  1. 使用is关键字判断类型
  2. 使用 as 关键字进行强制转换
// Main函数中
           

使用 as 关键字进行强转即使不成功也不会报错, 而是返回 null, 但是强行的 "ozb = (OstableZomby)zb" 转换如果不成功的话, 程序就会报错终止.

那么现在我们就是将数组问题解决了:

// Main函数中
           
C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

五.封装

在C#中, 可以把类里面的这些字段进行私有化保护, 并为其添加共有属性, 在类的外面不能通过对象直接访问这些字段, 想要访问只能通过访问属性的方式来完成, 这就是封装. 具体操作在记录属性的时候其实就已经写了, 这里就不再记录了.

补充.结构体和类的区别:

  1. 结构体是值类型, 而类是引用类型;
  2. 结构体只能有两个构造方法, 一个是无参默认的( 且不能显式写出来! ), 一个是将所有字段都初始化的;
  3. 结构体不能被继承, 而类可以被继承;
  4. 类有多态性, 结构体没有多态性;
  5. 一般只操作一些数据或是以数据为主的用结构类型, 当表示有一些层级关系的时候用类;
  6. 结构体有装箱拆箱的操作(值类型), 而类没有装箱拆箱的操作(引用类型);
int 
           

=======================================================

思维导图

C# 子类实例化基类 基类使用不了子类的方法_C#学习笔记09--构造方法/析构方法/继承/多态/封装...

继续阅读