1.继承

        1.基本概念

                一个类A继承类B,类B称为父类(基类、超类),类A被称为子类(派生类)。类A将会拥有B类的所有成员以及所有特征和行为。

                注意:子类可以有自己的特征和行为

        2.基本语法

class 父类米名
{

}

class 子类名: 父类名
{


}

        3.特点:

                1.单根性:子类只能有一个父类

                2.传递性:子类可以间接继承父类的父类(子类下面可以有n个子类)

// 基类/父类
public class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
    
    public void Eat()
    {
        Console.WriteLine($"{Name} is eating.");
    }
}

// 派生类/子类
public class Dog : Animal  // 使用冒号表示继承
{
    public string Breed { get; set; }
    
    public void Bark()
    {
        Console.WriteLine("Woof! Woof!");
    }
}

        4.受访问修饰符的影响

                1.public        公有的

                2.private        私有的,在外部和子类都不可以被访问

                3.protected    保护的,内部和子类可以访问,外部不可以访问 

        5.子类和父类同名的成员

                C#中允许子类和父类存在同名的成员,但不建议使用。

class P1
{
    public string name;
}

class P2: P1
{
    // public string name; // 不建议这样写
    public new string name; // (建议这样写)使用new隐藏父类字段,覆盖了父类同名的成员
}

// 实例化
var obj = new P2();

obj.name = "子类值";          // 访问 P2.name

//  (P1)obj:类型转换​,​​显式转换​​将P2类型转换成P1类型

((P1)obj).name = "父类值";    // 访问 P1.name

2.里氏替换原则

        1.概念:

                任何父类出现的地方,子类都可以替代。

                语法表现——父类容器装子类,因为子类对象包括了父类的所有内容

                作用: 方便进行对象的存储和管理

        2.实例

class Gameobject
{

}

class Player: Gameobject
{
    
    public void PlayerPrint()
    {
        Console.WriteLine("玩家");
    }

}

class Boss: Gameobject
{
    public void BossPirnt()
    {
        Console.WriteLine("Boss");
    }
}


// 里氏替换原则(用父类容器装载子类对象)
Gameobject player = new Player();
Gameobject boss = new Boss();

// 初始化对象数组
GameObject[] objects = new GamneObject(new Player(), new Boss());

3.is 和 as(一般配合使用)

        1.is 基本概念

                is 判断一个对象是否是指定类对象,返回值是bool类型

对象 is 类型


class Player
{

}


Player player = new Player();

if(player is Player)
{

}

object obj = "Hello";

if (obj is string)  // 检查是否为string类型
{
    Console.WriteLine("obj是字符串");
}

if (obj is int)     // 检查是否为int类型
{
    Console.WriteLine("obj是整数");
}

        2.as 基本概念

                as (只能用于引用类型或空值类型),将一个对象转换成指定类对象

                返回值:转换成功返回转换成功的对象,转换失败返回null

        补充:可空值类型是 C# 中用于表示"可能有值,也可能为 null"的值类型的特殊结构。

// 可空值类型


类型? 变量名;

// 等价于

Nullable<类型> 变量名;
// 引用类型转换
object obj = "Hello";
string str = obj as string;  // ✅ 合法:string是引用类型

// 可空值类型转换
object num = 42; // object 所有类型的终级基类
int? nullableInt = num as int?;  // ✅ 合法:int?是可空值类型

3.继承中的构造函数

        1.构造函数概念

                实例化对象时调用的函数,主要是用来初始化成员变量的,每一个类都会有一个默认的无参构造函数

        2.继承中的构造函数

                1.特点:当声明了一个子类对象时,先执行父类的构造函数,再执行子类的构造函数

                2.注意:

                        1.父类的无参构造函数很重要(子类必须调用父类的构造函数(直接或间接)

                        2.子类可以通过 base 关键字代表父类调用父类的构造函数(显式指定)

                        3.不能在同一个构造函数中多次使用base

                4.父类的无参构造函数很重要。子类实例化时,默认自动调用的是父类的无参构造函数,所有如果父类无参构造函数被覆盖了,则子类无法调用父类的无参构造函数(报错)。所有当父类的无参构造函数被覆盖时,要显式指定(base)调用哪个构造函数

class Parent
{
    public Parent(int id) { }  // 带参构造
    public Parent(string name) { }
}


class Child1 : Parent
{
    public Child() { }  // ❌ 编译错误
}


class Child2 : Parent
{
    public Child() : base(0) { }  // ✅ 显式传参
}

class Child3 : Parent
{
    public Child(int id) : base(id) { }  // ✅ 参数传递给父类
    public Child(int id) : base(string name), base(id) { }  // ❌ 错误!不能多次调用不同的基类构造函数
}

        base:调用父类的构造函数

        this:调用当前类其他构造函数(构造函数的链式调用)

4.万物之父

        1.基本概念

                object是所有类型的基类,它是一个引用类型

                关键字:object

                作用:

                        1.可以利用里氏替换原则,用object容器装载所有对象

                        2.可以用来表示不确定类型,作为函数参数类型

// 显式继承
class MyClass : Object { }

// 隐式继承(编译器自动添加)
class MyClass { }  // 等价于 class MyClass : Object

// 值类型也继承自Object
struct MyStruct { }  // 结构体也继承自Object

// 甚至基本类型也继承自Object
int number = 42;
string text = "hello";
class Father
{

}

clas Son: Father
{

}

static void Main(string[] args)
{

    Object obj = new Son(); 
}

2.装箱和拆箱

        1.装箱:将值类型转换为引用类型(object或接口类型)的过程

                过程:

                       1.在堆(heap)上分配内存                

                       2.将值类型的值复制到堆上新分配的对象中

                       3.返回新对象的引用

        2.拆箱:将引用类型转换回值类型的过程

                过程:     

                       1.检查对象实例是否为给定值类型的装箱值       

                       2.将值从实例复制到值类型变量中

int i = 123;      // 值类型
object o = i;     // 装箱 - 将int装箱到object中
int j = (int)o;   // 拆箱 - 将object拆箱回int

        3.好处与坏处

                好处:不确定类型时可以方便参数的存储和传递

                坏处:存在内存迁移,增加了性能消耗

5.密封类和密封方法

        1.密封类基本概念:

                使用 sealed 关键字修饰的类。该类无法被继承。在面向对象程序设计中,密封类的主要作用就是不允许最底层子类被继承。可以保证程序的规范性、安全性。加强了程序设计的结构性、安全性。

// 基本语法
访问修饰符 sealed class Person
{

}

sealed class Person
{

}

        2.密封方法的基本概念

                使用 sealed 关键字修饰的方法,该方法不能被重写。

                注意:sealed关键字不能直接用于普通方法,只能用于 ​​重写的方法(override)。也就是说不能直接定义密封方法。只能重写时,对其进行密封。

public class BaseClass
{
    
    // 普通方法
    public virtual void NormalMethod() { }
    
    public virtual void MethodToSeal() { }
}

public class DerivedClass : BaseClass
{
    // 可以重写普通虚方法
    public override void NormalMethod() { }
    
    // 重写并密封方法 - 后续派生类不能再重写此方法
    public sealed override void MethodToSeal() { }
}

public class FurtherDerivedClass : DerivedClass
{
    public override void NormalMethod() { }  // ✅ 可以重写
    
    // ❌ 编译错误:无法重写密封方法
    // public override void MethodToSeal() { }
}

        

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐