类声明的全貌

Class declarations.
024,025 类的声明,继承和访问控制 - 图1

C# 类声明的位置

  • 在名称空间里

    1. namespace HelloClass
    2. {
    3. class Program
    4. {
    5. ...
    6. }
    7. ...
  • 放在显式的名称空间之外实际上是声明在了全局名称空间里面,这是把类声明在名称空间的一种特殊情况。 ```csharp namespace HelloClass { … } class Computer {

}

  1. - 声明在类体里面(成员类)成员类在学习时不常见,但实际项目中常用。
  2. ```csharp
  3. namespace HelloClass
  4. {
  5. class Program
  6. {
  7. ...
  8. class Student
  9. {
  10. ...
  11. }
  12. }
  13. }

声明即定义(C# 与 Java)

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

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

最简单的类声明

语法:
024,025 类的声明,继承和访问控制 - 图2

即使是 ASP.NET Core 这么大的项目里面也没有特别复杂的类声明。

类成员的访问控制

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

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

Code Snippet

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

类的继承

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

  • 横向扩展:对类成员个数的扩充
  • 纵向扩展:对类成员(重写)版本的更新

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

  1. namespace HelloOOP
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. var t = typeof(Car);
  8. var tb = t.BaseType;
  9. var top = tb.BaseType;
  10. Console.WriteLine(tb.FullName);
  11. Console.WriteLine(top.FullName);
  12. Console.WriteLine(top.BaseType == null);
  13. }
  14. }
  15. class Vehicle {}
  16. class Car : Vehicle {}
  17. }

024,025 类的声明,继承和访问控制 - 图3

is a 概念

is a:一个派生类的实例,从语义上来说也是一个基类的实例。

  1. var car = new Car();
  2. Console.WriteLine(car is Vehicle);
  3. Console.WriteLine(car is Object);
  4. var vehicle = new Vehicle();
  5. Console.WriteLine(vehicle is Car);

024,025 类的声明,继承和访问控制 - 图4

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

知识点

  • sealed 封闭类,无法被继承024,025 类的声明,继承和访问控制 - 图5
  • C# 只支持单继承024,025 类的声明,继承和访问控制 - 图6注:C++ 支持多继承,但它也受菱形继承的困扰
  • 子类的访问权限不能超越父类024,025 类的声明,继承和访问控制 - 图7

类成员的访问级别

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

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

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

关键字 访问级别
public 024,025 类的声明,继承和访问控制 - 图8
protected internal 024,025 类的声明,继承和访问控制 - 图9
internal 024,025 类的声明,继承和访问控制 - 图10
protected 024,025 类的声明,继承和访问控制 - 图11
private 024,025 类的声明,继承和访问控制 - 图12

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. }