类声明的全貌

  • 类声明与创建类实例不同
  • C#类声明的位置:
    • 在namespace内,常用
    • 在类内,即成员类
    • 在namespace外,也是在全局namespace内
  • 在C#和java中声明即定义,在C++中声明与定义分开了(也可以合并在一起)

类的访问控制,类修饰符

  • public:跨程序集访问
  • internal:默认的访问级别,只能在当前程序集访问
  • static:静态类
  • abstract:修饰后表示为抽象类,不能被实例化,只能作为基类或多态使用
  • sealed:修饰后表示为封闭类,不能被继承
  • new:使用与嵌套类,指定类隐藏同名的继承成员
  • protected:在类作为成员类时,才能用此修饰符
  • private:在类作为成员类时,才能用此修饰符

    如何写出优质的代码——阅读、参考优质的开源项目代码

类的继承

  • 类的继承(基类、基接口):是子类在完整接收父类的前提下,对父类进行横向,或纵向扩展
    • 横向扩展:对类成员个数扩充
    • 纵向扩展:对类成员版本更新或重写override
  • 类在功能上的扩展(extend)
  • 只能有一个基类,但可以实现多个基接口
    • 基类与派生类是成对出现
    • 父类与子类是成对出现
  • 类访问级别对继承的影响
  • sealed类不能被继承
    • 是一个(is a)概念:派生类的实例也是基类的一个实例(反之不成立),可以用父类类型的变量来引用子类类型的实例
    • 当一个类被sealed修饰时,表示此类为封闭类,无法被继承,无法派生一个新类
    • 子类的访问级别不能超过父类的访问级别(internal,public)
    • “is a”示例: ```csharp using System;

namespace HelloOOP { class Program { static void Main(string[] args) { Car car = new Car(); Console.WriteLine(car is Vehicle);//输出:True

  1. //is a更深入的概念:多态
  2. Vehicle v = new Car();
  3. Object o1 = new Vehicle();
  4. Object o2 = new Car();
  5. }
  6. }
  7. class Vehicle
  8. {
  9. //Vehicle是基类
  10. }
  11. class Car : Vehicle
  12. {
  13. //Car是派生类
  14. }

}


<a name="t7oZl"></a>
# 成员的继承

- 派生类对继承成员的访问
- 派生类对基类成员的访问
- 构造器的不可继承性:需用base来写子类构造器
- 示例1:子类对父类成员的全盘继承,类成员只能增加不能减少(因此在新增类成员时必须警慎,否则会造成污染)
```csharp
using System;

namespace HelloOOP
{
    class Program
    {
        static void Main(string[] args)
        {
            RaceCar raceCar = new RaceCar();
            raceCar.Owner = "RaceCar";//raceCar有Owner属性,因此子类对父类的成员会全盘继承

            Car car = new Car();//创建继承链上的对象时,先调用父类构造器,后调用子类构造器
            Console.WriteLine(car.Owner);
        }
    }
    class Vehicle
    {
        public Vehicle()
        {
            this.Owner = "N/A";
        }
        public string Owner { get; set; }
    }

    class Car : Vehicle
    {
        //当子类构造器被调用时,父类构造器一定会被先于调用
        public Car()
        {
            this.Owner = "Car Owner";
        }

        public void ShowOwner()
        {
            Console.WriteLine(this.Owner);
            Console.WriteLine(base.Owner);//base表示父类对象,且只能向上访问一层
            //由于子类继承父类的Owner,所以this.Owner与base.Owner在内存中指向的是同一个值,因此this和base可以省略
            //如果父类的Owner访问级别是private,则此处不能用base.Owner,因为Owner虽然被继承了,但无权限访问
        }
    }

    class RaceCar : Car
    {

    }
}
  • 示例2:父类的实例构造器不能被子类继承。如果父类有一个带参数的构造器,由于不能被继承,子类构造器必须进行改写,如下: ```csharp using System;

namespace HelloOOP { class Program { static void Main(string[] args) { Car car = new Car();//方式一调用 Console.WriteLine(car.Owner);

        Car car1= new Car("Tim");//方式二调用
        Console.WriteLine(car1.Owner);
    }
}

class Vehicle
{
    public Vehicle(string owner)
    {
        this.Owner = owner;
    }
    public string Owner { get; set; }
}

class Car : Vehicle
{
    //父类构造器带参数,子类构造器改写方式一:
    //表示子类在调用父类构造器时,将string类型的"N/A"传给父类构造器
    public Car() : base("N/A")
    {
        this.Owner = "Car Owner";
    }

    //方式二
    public Car(string owner):base(owner)
    {

    }

    public void ShowOwner()
    {
        Console.WriteLine(Owner); 
    }
}

}


<a name="QeGdq"></a>
# 成员的访问级别

- 是以类的访问级别为上限的,如果一个类库中的类访问级别是internal(即类名前无修饰),那么即使类成员被public修饰,在其他程序集也无法访问此类的成员。
- 在A程序集引用B程序集的名称空间时,B程序集中必须要有类为public,写using时才能看到B程序集的名称空间
   - public:表示类成员是可以跨程序集被访问
   - internal:表示类成员只能在当前程序集被访问
   - private:
      - 默认访问级别,表示类成员只能在当前类中被访问
      - 父类的private成员在子类中可以被继承,但子类没权限访问
   - protected:
      - 只能被继承链上的对象/类访问,无法被其他类访问,且为跨程序集的
      - 设计时,应考虑此成员仅内部继承链上使用,其他类封装不显示,多用于方法中(重写)
      - protected可以和internal一起使用,为"或"关系,既可以被其派生类访问,又可以被当前程序集中所有其他类访问
   - 示例:创建MyLib类库,如下:
```csharp
using System;

namespace MyLib
{
    public class Vehicle
    {
        //_rpm字段,子类可以访问,而对其他类进行封闭,所以设计时用protected修饰
        protected int _rpm;
        //_fuel字段,只能在当前类中进行访问
        private int _fuel;

        //Refuel方法设计时为公开的,每个人都可以进行加油操作
        public void Refuel()
        {
            _fuel = 100;
        }

        //Burn方法由于其燃油功能为交通工具内部方法,只能被继承链上的类访问,不能被其他类使用
        protected void Burn(int fuel)
        {
            _fuel -= fuel;
        }

        //增速方法,设计为公开的方法
        public void Accelerate()
        {
            Burn(1);
            _rpm += 1000;
        }

        //只读属性Speed
        public int Speed
        {
            get{return _rpm/100;}
        }
    }

    public class Car : Vehicle
    {
        //Car子类新增TurboAccelerate方法,并继承父类Vehicle所有成员
        public void TurboAccelerate()
        {
            Burn(2);
            _rpm += 3000;//父类_rpm为protected时可以访问,如果为private则无法访问
        }
    }
}
    在主程序中编写如下代码:
using System;
using MyLib;

namespace HelloAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            Car car = new Car();
            car.Refuel();//先加满油
            car.TurboAccelerate();//在进行一次加速
            Console.WriteLine(car.Speed);
        }
    }

    class Bus : Vehicle
    {
        public void SlowAccelerate()
        {
            //被protected修饰的成员,可以被跨程序集的子类访问
            Burn(1);
            _rpm += 500;
        }
    }
}

面向对象的实现风格

  • Class-based:基于类的面向对象系统,在C++、Java、C#中运用
  • Prototype-based:基于原型的面向对象系统,在javascript中运用