第9章继承和访问控制 集,, 9.1类的继承 911基类与派生类 实际上每一个类的声明都在隐式地继承 System Object类;通常, 我们所讲的继承是指显式的继承。在语法上,继承是在类声明的 同时完成的。在类名标识符后加上冒号“:”,冒号后面是基类, 因为只有单继承,所以基类只有一个。 派生类继承基类中除了构造函数和析构函数以外的字段、属性、 索引器、事件、方法等所有成员。派生类可以定义自己的成员, 也就是说,在获得基类从成员同时再增加自己的成员
第9章 继承和访问控制 9.1.1 基类与派生类 实际上每一个类的声明都在隐式地继承System.Object类;通常, 我们所讲的继承是指显式的继承。在语法上,继承是在类声明的 同时完成的。在类名标识符后加上冒号“ : ”,冒号后面是基类, 因为只有单继承,所以基类只有一个。 派生类继承基类中除了构造函数和析构函数以外的字段、属性、 索引器、事件、方法等所有成员。派生类可以定义自己的成员, 也就是说,在获得基类从成员同时再增加自己的成员。 ◼ 9.1 类的继承
9.1类的继承 集,, ■9.1.2成员的继承、添加和隐藏 派生类重新定义一个与从基类继承来的字段完全相同的字 段变量,称为字段的隐藏,表示新的字段挡住了来自基类的字段 但是这并不是意味着来自基类的字段不存在了,或者不能用了, 而是表示被隐藏的字段只能被来自同样基类的方法所访问,如果 派生类一定要访问被隐藏的字段,则需要在该字段前加上 “base.”以表示是来自基类的同名字段 当派生类中必须隐藏基类的字段时,为了清晰地表明派生 类隐藏基类同名字段的意图,派生类中的同名字段应该使用new 修饰符,否则编译时会有提示性的警告
9.1 类的继承 派生类重新定义一个与从基类继承来的字段完全相同的字 段变量,称为字段的隐藏,表示新的字段挡住了来自基类的字段。 但是这并不是意味着来自基类的字段不存在了,或者不能用了, 而是表示被隐藏的字段只能被来自同样基类的方法所访问,如果 派生类一定要访问被隐藏的字段,则需要在该字段前加上 “base.”以表示是来自基类的同名字段。 当派生类中必须隐藏基类的字段时,为了清晰地表明派生 类隐藏基类同名字段的意图,派生类中的同名字段应该使用new 修饰符,否则编译时会有提示性的警告。 ◼ 9.1.2 成员的继承、添加和隐藏
91.3关键字base ■9.1.3.1使用base访问基类的字段和方法 当调用被隐藏的基类的成员,则base是必须的。 ■9.1.32使用base调用基类的构造函数 派生类继承基类中除了构造函数、析构函数以外的所有成员,但是,派生 类仍然可以调用直接基类的构造函数 91.3.3使用base的注意点 口base指对象,不能用在静态方法和构造函数中,也不能通过base访问其它静态成员; 口直接基类也可以是派生类,拥有来自它自己的基类的成员,派生类中使用base关键字 不区分直接基类成员的来源,都同样地用base来访问; 口派生类使用base只能调用直接基类的构造函数。 口只能在派生类内用base访问基类的被隐藏的成员,在派生类之外,不能通过派生类的 对象访问被隐藏的成员
9.1.3 关键字base ◼ 9.1.3.1 使用base访问基类的字段和方法 当调用被隐藏的基类的成员,则base是必须的。 ◼ 9.1.3.2 使用base调用基类的构造函数 派生类继承基类中除了构造函数、析构函数以外的所有成员,但是,派生 类仍然可以调用直接基类的构造函数。 ◼ 9.1.3.3 使用base的注意点 ❑ base指对象,不能用在静态方法和构造函数中,也不能通过base访问其它静态成员; ❑ 直接基类也可以是派生类,拥有来自它自己的基类的成员,派生类中使用base关键字 不区分直接基类成员的来源,都同样地用base来访问; ❑ 派生类使用base只能调用直接基类的构造函数。 ❑ 只能在派生类内用base访问基类的被隐藏的成员,在派生类之外,不能通过派生类的 对象访问被隐藏的成员
92访问控制符 访问控制符是一种类和类成员的修饰符,用来控制类或类成 员的可访问性。访问控制符有五个: public、 protected internal、 protected internal和 private。访问控制符限定了被 修饰对象的可访问性。可访问性指出了一个范围,在这个范 围内的程序可以访问被修饰的对象,访问控制符有显式的和 默认的两种
9.2 访问控制符 访问控制符是一种类和类成员的修饰符,用来控制类或类成 员的可访问性。访问控制符有五个:public、protected、 internal、protected internal和private。访问控制符限定了被 修饰对象的可访问性。可访问性指出了一个范围,在这个范 围内的程序可以访问被修饰的对象,访问控制符有显式的和 默认的两种
921访问控制符和可访问性(1) 其中C和D的并集表示了类 B的所有派生类。设B中的 F;所有类 某成员用如下访问控制符 Ai:添程序 修饰,那么它的可访问性 w程ACc:程集A之外的派 见表9.1。 的生樂:生类 如果没有对类成员使用访 问控制符,那么该成员被 默认为 private可访问性, 规定类成员的默认的访问 图91可访问的控制区域 控制符为 private
9.2.1 访问控制符和可访问性(1) E:所有类 A:本程序集 C:程序集A 之外的派 生类 D:程序集A 中的派生类 B:本类 图9.1 可访问的控制区域 其中C和D的并集表示了类 B的所有派生类。设B中的 某成员用如下访问控制符 修饰,那么它的可访问性 见表9.1。 如果没有对类成员使用访 问控制符,那么该成员被 默认为private可访问性, 规定类成员的默认的访问 控制符为private
921访问控制符和可访问性(2) 访问控制符可访问的范围 含义 public E 访问不受限制 protected B+C+D 被所在类和该类的派生类访问 internal A(包括B和D)被该类所在的程序集访问 protected A(包括B)+C+D包含类、包含类的派生类、所 internal 在的程序集 private B 包含类
9.2.1 访问控制符和可访问性(2) 访问控制符 可访问的范围 含义 public E 访问不受限制 protected B+C+D 被所在类和该类的派生类访问。 internal A(包括B和D) 被该类所在的程序集访问 protected internal A(包括B)+C+D 包含类、包含类的派生类、所 在的程序集 private B 包含类
922继承 private成员和 protected成员 基类的 private成员被派生类所继承后,派生类拥有基类的 private成 但是派生类中新定义的方法不能访问来自基类的 private成员。 派生类的成员分为继承基类的部分和新定义的部分,来自基类的 private成员只能被来自基类的方法所调用。 受保护的类成员和私有的类成员在没有继承的条件下是一样的,在存 在继承关系的情况下,因为派生类有两个部分组成,一部分是从基类 继承而得,另一部分是派生类添加的成员,对于基类的 private成员 其可访问性只限于来自基类的部分;而基类的 protected成员的可访 问性为派生类的全部 继承是可传递的,如果类B继承类A,类C继承类B,那么对C而言来自A 和B的成员都是来自基类的成员,地位是等同的。 理解可访问性的基本要领是判定成员的作用域,不能从作用域之外访 问该成员。但是作用域的判定有时不能仅仅从形式上判别,有时要看 上下文
9.2.2 继承private成员和 protected成员 基类的private成员被派生类所继承后,派生类拥有基类的private成 员,但是派生类中新定义的方法不能访问来自基类的private成员。 派生类的成员分为继承基类的部分和新定义的部分,来自基类的 private成员只能被来自基类的方法所调用。 受保护的类成员和私有的类成员在没有继承的条件下是一样的,在存 在继承关系的情况下,因为派生类有两个部分组成,一部分是从基类 继承而得,另一部分是派生类添加的成员,对于基类的private成员, 其可访问性只限于来自基类的部分;而基类的protected成员的可访 问性为派生类的全部。 继承是可传递的,如果类B继承类A,类C继承类B,那么对C而言来自A 和B的成员都是来自基类的成员,地位是等同的。 理解可访问性的基本要领是判定成员的作用域,不能从作用域之外访 问该成员。但是作用域的判定有时不能仅仅从形式上判别,有时要看 上下文
9.23访问控制符的约束(1) 表9.2语言成分的可访问性和访问控制符 默认或隐含的可访问性 默认或隐含的可访问性 名空间 public(隐含) 不允许 非成员的类型 internal public、 internal 类成员 private 全部(见表9-1) 结构成员 private Public、 internal、 private(不能 使用 protected) 接口成员 public(隐含) 不允许 枚举成员 public(隐含) 不允许
9.2.3 访问控制符的约束(1) 表9.2 语言成分的可访问性和访问控制符 默认或隐含的可访问性 默认或隐含的可访问性 名空间 public(隐含) 不允许 非成员的类型 internal public、internal 类成员 private 全部(见表9-1) 结构成员 private Public、internal、private(不能 使用protected) 接口成员 public(隐含) 不允许 枚举成员 public(隐含) 不允许
9.23访问控制符的约束(2) 表9.3可访问性的约束 上下文 上下文 类 类类型的直接基类必须至少与类类型本身具有同样的可访问性 接口接口类型的显式基接口必须至少与接口类型本身具有同样的可访问性 委托委托类型的返回类型和参数类型必须至少与委托类型本身具有同样的 可访问性 常数常数的类型必须至少与常数本身具有同样的可访问性 字段字段的类型必须与至少字段本身具有同样的可访问性 方法方法的返回类型和参数类型必须至少与方法本身具有同样的可访间性
9.2.3 访问控制符的约束(2) 表9.3 可访问性的约束 上下文 上下文 类 类类型的直接基类必须至少与类类型本身具有同样的可访问性 接口 接口类型的显式基接口必须至少与接口类型本身具有同样的可访问性 委托 委托类型的返回类型和参数类型必须至少与委托类型本身具有同样的 可访问性 常数 常数的类型必须至少与常数本身具有同样的可访问性 字段 字段的类型必须与至少字段本身具有同样的可访问性 方法 方法的返回类型和参数类型必须至少与方法本身具有同样的可访问性
9.23访问控制符的约束(3) 表9.3可访问性的约束一续 上下文 上下文 属性属性的类型必须至少与属性本身具有同样的可访问性 事件事件的类型必须至少与事件本身具有同样的可访问性 索引器索引器的类型和参数类型必须至少与索引器本身具有同样的可访问性 运算符运算符的返回类型和参数类型必须至少与运算符本身具有同样的可访 问性 构造函构造函数的参数类型必须至少与构造函数本身具有同样的可访问性
9.2.3 访问控制符的约束(3) 表9.3 可访问性的约束—续 上下文 上下文 属性 属性的类型必须至少与属性本身具有同样的可访问性 事件 事件的类型必须至少与事件本身具有同样的可访问性 索引器 索引器的类型和参数类型必须至少与索引器本身具有同样的可访问性 运算符 运算符的返回类型和参数类型必须至少与运算符本身具有同样的可访 问性 构造函 数 构造函数的参数类型必须至少与构造函数本身具有同样的可访问性