[25] Learning C # class inheritance, class member access

  • Statement class inheritance syntax: after the class name followed by a colon [:], [after the colon write a base class, interfaces or base ]; base classes and base interfaces collectively referred to as [Basics]

  • The term & specification: a base class and a derived class; parent class and subclass

  • If there is no means BenQ class as a class, is actually derived from System.Object [], a class of the base class of all types, since the system is a single type .NET, so Object class inheritance chain at the top of all types of

[A (is a)] concept

Examples of a subclass, semantically, is an instance of the parent class
For example: a student, but also a person; a car is a vehicle ...
Here Insert Picture Description
A parent class may be used to refer to an instance variable of the type of a sub-class type of

Little knowledge

(1) with a "sealed" [class is called modified closed type ], the class can not be closed as a base class

(2) C # system, a class can only have one base class, but can implement multiple base interfaces
specifications:
[inherited from, is derived from a base class]; [achieved] a base interface

(3) access level can not exceed subclass the parent class, the access level can be flat with the parent class, or lower than the
example: the level of access the parent can not appear to [Internal], and the access level subclass is the case of [public]

And the impact of the derived class member inheritance

The nature of inheritance

The nature of the derived class inheritance is based on the existing transverse members above the base class, the base class for the extension in the longitudinal direction
Understand
(1) derived classes based on currently available members of the base class: When inheritance occurs, the sub-class member of the parent class to get the overall

(2) In the process of derivation and inheritance, the operation is [extensions]: extension, indicating that class members can only be more and more, less and less is impossible - you can add a class member, but can not be added after once then remove
a class member, once introduced into the inheritance chain, which will have been passed down, can no longer be removed; so during class design / design library, must be very careful not to rush the introduction of new members otherwise, it might be the inheritance chain, API pollution
[class members can only be extended, not cut] is a static class language (such as C #, Java) features; dynamically typed languages (such as python, JS) can be added at any time, class members removed

(3) horizontal, vertical: [] refers to the lateral extension class members in number; [longitudinal] is the version of the class members will be expanded, expanded version / updated version called [rewrite]

The sample program
1. subclass of class members of the parent class [accept it], and can only increase class members can not be removed
other words: a sub-class members of any class in the parent class can not in the inheritance chain remove, C # does not support this operation, so there is no keywords, operators can achieve this functionality

2. What is the base class object?

First clear:When you create an instance of a class on the inheritance chain, it will first trigger the base class constructor, to construct the base class object []
Here Insert Picture Description

Memory Mechanism (guess)
(1) car [Car]: see [car] When a computer is a reference type variable, and immediately go to [] in the stack for cutting out 4 bytes of memory space, and the whole value memory brush into 0 It indicates that the variable has not cited any instance

(2)] [new Car: create an instance of the class represented, the computer immediately stack [] to find vacant position, and the corresponding memory space cut members according to the class, since the constructor has not been called, so this case the memory has not been allocated (Owner field and ShowOwner () method of the respective numbers of bytes) and initialization

(3)【( )】:表示调用Car类的实例构造器,但在调用之前,会先去调用其基类【Vehicle的构造器】,就会在【堆内存】中创建出一个【基类对象】,由于Owner字段的数据类型 string 属于引用类型,所以基类对象所代表的这段内存(4个字节)中存储的是一个地址——Owner字段的实例在堆内存中的位置

(4)在基类的构造器中,将 “N/A” 赋值给Owner字段(也就是创建出了Owner字段的实例),“N/A” 这个实例在堆内存中的地址就传给了【基类对象】,那么基类对象所代表的内存块中就存储了值(这个值是 “N/A” 的地址),并继承给【new Car】所创建出来的实例

(5)由于new Car 所创建出来的实例继承了 “N/A” 的地址,所以此时该实例的Owner字段值也是 “N/A”

(6)接着开始调用派生类【Car类的构造器】:在Car的构造器中,将实例的Owner字段值【重写】为 “Dave”,注意:【基类对象和new Car出来的对象中存储的地址并没有改变,只是该地址所指向的内存块中存储的值发了生变化,由 "N/A"变为 “Dave”】

(7)完成了调用【Car类的构造器】,new Car 出的对象所代表的内存也就被成功分配和初始化了,这段内存所在的地址就会交还给【变量car】,从而完成变量car对实例的引用

(8)调用 car的ShowOwner()方法,打印出【car所引用的实例和基类对象的Owner字段值】,也就是this.Owner和base.Owner,应都为 “Dave”

(9)由于基类对象并没有变量引用,是一个【没有小孩牵着的气球】,所以一段时间后就会被垃圾收集器回收

简化示意图
Here Insert Picture Description

提醒:
(1)属性是字段的包装器,属性的简化声明是语法糖,字段是存在的

(2)示意图中左侧橙色部分表示被操作系统占用的内存

(3)内存中的值(包括地址)皆用二进制表示

  • 为什么在创建子类对象时,会先调用父类构造器?
    因为创建一个实例,需要调用其构造方法,来初始化它的实例成员,而子类拥有父类的成员变量和成员方法,如果不去调用父类的构造器,那么这些从父类继承而来的成员则得不到正确的初始化

  • 如何调用父类构造器?
    子类构造器会默认调用父类的无参构造器,如果父类没有无参构造器(也就是自定了父类的构造器),则需在子类构造器的第一行显示调用父类的其他构造器,否则会报错
    Here Insert Picture Description
    Here Insert Picture Description
    Here Insert Picture Description
    父类的实例构造器,是不能被子类所继承的

3.类成员的访问级别

原则:类成员的访问级别是以类的访问级别为上限的
比如说:如果一个类的访问级别为 Internal,就算该类的成员的访问级别为 public,在其他程序集中也是看不到这些类成员的

【注意区分】
类的访问级别:public,Internal
类成员的访问级别:public,Internal,private,protected
public级别和Internal级别在类中已经做过整理,这两个级别修饰类成员时可以很清晰地做出类比,故不再赘述

(1)private

【private】将成员的访问级别限制在【类体】中,是最低的访问级别

用private修饰的成员称为【私有成员】,父类的私有成员是不能被子类及子类对象所访问的;继承归继承,但不能访问
Here Insert Picture Description

默认的访问级别是 【private】,这样做是为了保证数据的安全性,尽可能少地把数据和行为暴露到外界——封装
虽然是默认情况,但还是建议写上 “private” ,使代码更整齐明了

既然在子类中无法访问父类的私有成员,又如何证明该成员确实被继承了呢?
Here Insert Picture Description

“_rpm”:可以理解为一种约定俗成的写法,当看到一个变量名前有下划线,立刻就会知道它是一个【实例字段,而且是私有字段】

(2)protected

【protected】会把类成员的访问级别限制在继承链上
当父类中的类成员是用 protected 修饰时,它的所有子类都可以访问该成员,但其他不在继承链上的类型是无法访问的

代码示例:
Here Insert Picture Description

显然,Burn()方法的访问级别是不合理的;Refuel(),Accelerate()方法public 出去都可以,因为这两个方法可以且应该被外界所调用,加油和加速的操作应该是 “人” 来完成,但 Burn()方法不应该,【烧油是汽车自己的事】,是在汽车内部进行的,这个过程不是司机来完成的,也根本不该被司机看到——不能被司机所调用
所以,需要修改Burn()方法的访问级别为【protected】,保证其子类调用并继承就足够了

提醒:
在团队合作中,最好的不让类成员被别人调用的方法,就是别把这个类成员 public 出来,否则,如果对方没有阅读文档,或者文档写得不清楚,如果他发现调用这个成员可以解决自己的bug,那肯定会去调用的;这样一来,就可能会给自己以及整个团队造成麻烦

注意:
(1)【protected】是跨程序集的

(2)【protected】修饰符,更多地是应用于【方法】,因为类成员的纵向扩展(重写)和protected关系紧密

(3)【protected】和【Internal】可以组合,是 “或” 关系,顺序并无要求;也就是说:如果用 “protected” 和 “Internal” 共同修饰一个成员,那么该成员既可以被其派生类所访问,又可以被其所在的程序集当中的其他类所访问

  • 面向对象的实现风格
    包括:
    class—based
    prototype—based
    要以开放的心态去面对每一种编程语言
Published 29 original articles · won praise 3 · Views 933

Guess you like

Origin blog.csdn.net/weixin_44813932/article/details/104054527