1、什么是 “类”

类是一种数据结构,它可以包含数据成员(常量和字段)、函数成员(方法、属性、事件、索引器、运算符、实例构造函数、静态构造函数和析构函数)以及嵌套类型。类类型支持继承,继承是种机制,它使派生类可以对基类进行扩展和专用化。

  • 是一种数据结构(data structure)
  • 是一种数据类型
  • 代表现实世界中的“种类”
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Type t = typeof(Student);
            dynamic stu = Activator.CreateInstance(t, 1, "LDX");
            Console.WriteLine(stu.Name);
        }           
    }
   class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public Student(int id,string name)
        {
            ID = id;
            Name = name;
        }
        ~Student()//析构器
        {
            Console.WriteLine("Bye bye! Release the system resourse...");
        }
        public void Reprot()
        {
            Console.WriteLine($"i'm #{ID} student,my name is {Name}.");
        }

    }

}

2、类的声明

(1)类声明的全貌

  • C#类声明的位置
  • 声明既定义(C#与Java)
  • 类修饰符:new,public,protected,internal,private,abstract,sealed,static

(2)最简单的类声明

  • 类的访问控制

(3)类成员的访问控制

(4)类的继承

  • 派生类对基类的成员获得与访问
  • 在派生类中访间基类的成员
  • 构造器的不可继承性

3、类的继承

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

  • 类在功能上的扩展(extend)
  • 只能有一个基类,但可以实现多个其接口
  • 类访问级别对继承的影响:子类的访问级别不能超过父类
    • public,internal,private,protected(相比于private可以被同空间的其他类调用)
    • 相互组合时,是或的关系
  • sealed类不能被继承(在class前加sealed)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClassLibrary3.MyLib
{
    public class Vehicle
    {
        protected int _rpm;
        protected int _fuel;
        public void Refuel()
        {
            _fuel = 100;
        }
        protected void Burn()
        {
            _fuel--;
        }
        public void Accelerate()
        {
            Burn();
            _rpm += 1000;
        }
        public int Speed {get { return _rpm / 100; } }
       
    }
    public class Car : Vehicle
    {
        public void TurboAccelerate()
        {
            Burn();
            Burn();
            _rpm += 3000;
        }
    }
}

(1)成员的继承与访闻

  • 派生类对继承成员的访问
  • 派生类对基类成员的访问
  • 构造器的不可继承性

(2)面向对象的实现风格

  • Class-based
  • Prototype-based
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vehicle = new Car();//可以用父类变量引用子类实例
        }
    }
    class Vehicle 
    {
    }
    class Car:Vehicle
    {

    }

}
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
           Car car = new Car("LDX");
            Console.WriteLine(car.Owner);
        }
    }
    class Vehicle 
    {
        public string Owner { get; set; }
        public Vehicle(string owner)
        {
            this.Owner = owner;
        }
    }
    class Car:Vehicle
    {
        public Car(string owner):base(owner)
        {
            this.Owner = "Car Owner";//先调用父类,再调用子类;实例构造器不被继承
        }
    }
    

}

(3)类的继承

  • 类成员的“横向扩展”(成员越来越多)
  • 类成员的“纵向扩展”(行为改变,服本增高)
  • 类成员的隐藏(不常用)
  • 重写与隐藏的发生条件:函数成员,可见(public/protected),签名一致

(4)多态(polymorphism)

  • 基于重写机制(virtual > override)
  • 函数成员的具体行为(版本)由对象决定
  • 回顾: C#语言的变量和对象都是有类型的,所以会有“代差”
namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle car = new RaseCar();
            car.Run();
        }
    }
    class Vehicle
    {
        public virtual void Run()
        {
            Console.WriteLine("I'm running.");
        }
    }
    class Car:Vehicle
    {
        public override void Run()
        {
            Console.WriteLine("Car is running.");
        }
    }
    class RaseCar : Car
    {
        public override void Run()
        {
            Console.WriteLine("RaseCar is running.");
        }
    }
}

属性也可以进行重写

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Vehicle car = new Car();
            car.Run();
            Console.WriteLine(car.Speed);
        }
    }
    class Vehicle
    {
        private int _speed;
        public virtual int Speed
        {
            get{ return  _speed; }
            set{ _speed = value; }
        }
        public virtual void Run()
        {
            Console.WriteLine("I'm running.");
        }
    }
    class Car:Vehicle
        
    {
        private int _rpm;
        public override int Speed 
        { 
            get { return _rpm / 100; }
            set { _rpm = value * 100; }
        }
        public override void Run()
        {
            Console.WriteLine("Car is running.");
            _rpm = 5000;
        }
    }
    class RaseCar : Car
    {
        public override void Run()
        {
            Console.WriteLine("RaseCar is running.");
        }
    }
}