类声明的全貌

image.png

C# 类声明的位置

(1) 在名称空间里

  1. namespace HelloClass{
  2. class Program{
  3. ...
  4. }
  5. ...

(2) 放在显式的名称空间之外实际上是声明在了全局名称空间里面,这是把类声明在名称空间的一种特殊情况。

  1. namespace HelloClass{
  2. ...
  3. }
  4. class Computer{
  5. ...
  6. }

(3) 声明在类体里面(成员类)成员类在学习时不常见,但实际项目中常用。

  1. namespace HelloClass{
  2. class Program{
  3. ...
  4. class Student{
  5. ...
  6. }
  7. }
  8. }

声明即定义(C# 与 Java)

● C++ 里面类的声明和定义默认是分开的(推荐),也可以手动写到一起。

图一:C++声明部分( xxx.h ) 图二:C++定义部分( xxx.cpp ) 图三:C++实际应用部分( xxx.cpp ) ①声明后不定义,只要不调用内部方法等,就能够编译通过…否则报错(链接器报错)。image.pngimage.pngimage.png ②当然,C++声明和定义可以放在一块。(xxx.h中) image.pngimage.png

● 在 C# 和 Java 中声明即定义。

最简单的类声明

(17)类的声明,继承和访问控制 - 图7
即使是 ASP.NET Core 这么大的项目里面也没有特别复杂的类声明。
● 名称空间层级关系 与 类 …
image.pngimage.png

类的访问级别

class 前面没有任何修饰符等于加了 internal。

  • internal:仅在自身程序集(Assembly)里面可以访问(项目内)。
  • public:从 Assembly (装配集)暴露出去。

●类 权限暴露使用( public )。

不同项目中 要访问类的话,需要利用public暴露出来。 1657190069246.png

image.pngimage.png

Code Snippet

  1. F12:跳至类定义
  2. Ctrl + - (减号):跳回至之前所在位置

类的继承

类的派生与继承简述

①所有类最顶端的基类是System.Object类型。 ②基于基类继承如下:

image.png
Timothy:继承的本质是派生类在基类已有的成员基础上,对基类进行的横向和纵向的扩展。

  • 横向扩展:对类成员数量的扩充
  • 纵向扩展:对类成员(重写)版本的更新(数量不增加,版本进行扩充)

只能扩展不能缩减,这是静态类型语言(C#、C++、Java 等)的特征,继承时类成员只能越来越多。
动态类型语言(Python、JavaScript)可以移除类成员。

is a 概念

  1. var car = new Car();
  2. Console.WriteLine(car is Vehicle);//汽车是一个交通工具 True
  3. Console.WriteLine(car is Object);//汽车是一个对象 True
  4. var vehicle = new Vehicle();
  5. Console.WriteLine(vehicle is Car);//交通工具不一定特指汽车 False

(17)类的声明,继承和访问控制 - 图14

  1. // 可以用基类类型的变量来引用派生类实例
  2. Vehicle vehicle = new Car();
  3. Object o1 = new Vehicle();
  4. Object o2 = new Car();

知识点

●添加 sealed 关键字代表封闭类不能被继承

(17)类的声明,继承和访问控制 - 图15

C#只支持单继承!(一个类最多只能有一个基类)

image.png (1)规范名词: 1.基类:继承自某个基类 或 派生自某个基类。(只能有一个基类) 2.基接口:某个类实现了某个基接口…(可以有多个基接口) 注:C++ 支持多继承,但它也受菱形继承的困扰。

●子类的访问级别(权限)不能超越父类…

解释:基类限制在了Assembly内,但子类不能超越权限使用public…(反过来就可以) 1657224298146.png

实际案例

(1)基类的构造器先被触发,再触发子类的构造器。

先构造基类对象,再一级一级往下构造,最终构造出子类对象。image.png 问题解析:如下图为什么会报错? image.png 解释:①当构造器带参数后,就不会生成不带参数的默认构造器。 ②可是子类很自然的要调用默认构造器,找不到… 解决方案: 方案一:将父类具体值传入子类构造器中… image.png 方案二:子类也添加参数… image.pngimage.png

(2)综上所述,父类构造器是不会被继承的!!!

类成员的访问级别

●类成员的访问级别以类的访问级别为上限。

image.png image.pngimage.png

命名偏好

随着越来越多 C++、Java 程序员加入 .NET 社区,private 字段的命名普遍遵循 下划线 + 小写。
例:private int _rpm;

在团队合作中,自己写的类或方法不想被他人调用时,推荐的做法就是不用 public 进行修饰。
如果应该封装的成员没有封装,对方只要发现能够调用,又能解决问题,他就一定会去用,进而导致一些不确定的问题。

关键字 访问级别



public
(17)类的声明,继承和访问控制 - 图26



protected internal
(17)类的声明,继承和访问控制 - 图27



internal
(17)类的声明,继承和访问控制 - 图28



protected
(17)类的声明,继承和访问控制 - 图29



private
(17)类的声明,继承和访问控制 - 图30

C# 7.2 推出了最新的 Private Protected: The member declared with this accessibility can be visible within the types derived from this containing type within the containing assembly. It is not visible to any types not derived from the containing type, or outside of the containing assembly. i.e., the access is limited to derived types within the containing assembly.( Private Protected 仅对程序集内的派生类可见

面向对象的实现风格

开放心态,不要有语言之争。

我们现在学到的封装、继承、多态的风格是基于类的(Class-based)
还有另外一个非常重要的风格就是基于原型的(Prototype-based),JavaScript 就是基于原型的面向对象。

Java 也是基于类的,让我们一撇 Java:

  1. package com.ccc;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Car car = new Car();
  5. car.owner = "Timothy";
  6. System.out.println(car.owner);
  7. }
  8. }
  9. class Vehicle{
  10. public String owner;
  11. }
  12. class Car extends Vehicle{
  13. }