在这里插入图片描述

上一篇我们彻底搞懂了类与对象、构造函数、封装思想,成功从“堆砌代码的面向过程”迈入了“模块化的面向对象编程”。

我们已经学会了自定义类、实例化对象、私有化数据保护数据安全,但想要写出企业级标准代码、实现代码高度复用、适配复杂业务层级,仅靠封装远远不够。

面向对象编程(OOP)有三大黄金核心特性:封装、继承、多态。上一篇我们掌握了封装,本篇将补齐剩余两大核心,同时精讲C#专属的**属性(Property)**语法。

属性是封装的现代化升级版,继承是代码复用的核心,多态是项目解耦、灵活开发的关键。学完本篇,你将完整掌握C#面向对象全部核心能力,告别初级新手,迈入标准开发行列。

一、前置回顾:为什么要学这三个知识点?

我们先结合之前的代码,梳理痛点,明白学习的意义:

  1. 之前我们通过 Get/Set 方法管控私有字段,代码冗余繁琐,C# 属性 就是为了简化封装而生,是项目唯一标准写法;

  2. 多个相似的类(学生、老师、员工)存在大量重复字段和方法,反复编写代码浪费效率,继承 可以实现代码一键复用;

  3. 同一类事物存在不同行为,需要灵活适配不同场景,多态 可以实现一个接口、多种实现,让代码更灵活、易扩展。

三者结合,构成了C#所有项目、框架、游戏开发的底层基石。

二、C# 核心语法:属性(Property)——封装的终极形态

很多新手分不清字段属性,甚至混用公开字段写代码,这是项目开发的大忌。我们从零彻底理清。

1. 字段 vs 属性(核心区别)

  • 字段:类中定义的普通变量(private string _name),作用是纯存储数据,项目规范要求必须私有,禁止外部直接访问;

  • 属性:专门用来读写私有字段的特殊语法,是 Get/Set 方法的语法糖,简洁优雅,是C#官方推荐的唯一封装写法

2. 完整属性写法(带数据校验,企业标准)

完整属性包含 私有字段 + get读取器 + set赋值器,支持数据校验,完美实现封装。

using System;

class Student
{
    // 私有字段:仅类内部可访问
    private string _name;
    private int _age;

    // 姓名属性:控制读取和赋值
    public string Name
    {
        get
        {
            // 读取数据时返回私有字段
            return _name;
        }
        set
        {
            // 赋值时做数据校验,过滤非法数据
            if (!string.IsNullOrEmpty(value))
            {
                _name = value;
            }
        }
    }

    // 年龄属性:带严格范围校验
    public int Age
    {
        get => _age; // 简化Lambda写法
        set
        {
            if (value > 0 && value < 100)
            {
                _age = value;
            }
            else
            {
                Console.WriteLine("年龄输入不合法!");
            }
        }
    }
}

class Program
{
    static void Main()
    {
        Student stu = new Student();
        // 通过属性赋值(自动触发校验)
        stu.Name = "张三";
        stu.Age = 18;

        Console.WriteLine($"姓名:{stu.Name},年龄:{stu.Age}");

        // 非法数据被拦截
        stu.Age = -10;
    }
}

3. 自动属性(开发最常用)

如果不需要复杂数据校验,仅需封装数据,可直接使用自动属性,系统会自动隐藏生成私有字段,代码极度简洁,是日常开发高频写法。

class Student
{
    // 自动属性:系统自动生成私有字段
    public string Name { get; set; }
    public int Age { get; set; }
    // 只读属性:仅允许初始化,外部无法修改
    public int Id { get; }
}

4. 核心总结

永远不要在项目中使用 public 公开字段!所有对外数据交互,统一使用属性,这是C#开发的硬性规范。

三、面向对象核心:继承(Inheritance)——代码复用神器

继承是面向对象三大特性之二,核心作用:复用已有代码,实现层级分类,杜绝代码冗余

1. 核心概念

  • 父类(基类):通用、公共的模板类,提取所有子类的共性字段和方法;

  • 子类(派生类):继承父类的所有非私有成员,同时可以扩展自己独有的字段和方法;

  • C# 继承语法:class 子类 : 父类

2. 继承实战案例

场景:老师和人员都属于“人”,都有姓名、年龄、性别,但是老师有工资、学生有成绩,通过继承实现代码复用。

using System;

// 父类:人类(通用共性)
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    // 通用行为
    public void SayHello()
    {
        Console.WriteLine($"大家好,我是{Name},今年{Age}岁");
    }
}

// 子类:学生类,继承人类
class Student : Person
{
    // 学生独有属性
    public int Score { get; set; }

    public void Study()
    {
        Console.WriteLine($"{Name} 正在认真学习,成绩:{Score}");
    }
}

// 子类:老师类,继承人类
class Teacher : Person
{
    // 老师独有属性
    public double Salary { get; set; }

    public void Teach()
    {
        Console.WriteLine($"{Name} 正在授课,月薪:{Salary}");
    }
}

class Program
{
    static void Main()
    {
        // 学生子类复用父类属性和方法
        Student stu = new Student();
        stu.Name = "张三";
        stu.Age = 18;
        stu.Score = 95;
        stu.SayHello();
        stu.Study();

        // 老师子类复用父类属性和方法
        Teacher tea = new Teacher();
        tea.Name = "李老师";
        tea.Age = 35;
        tea.Salary = 8000;
        tea.SayHello();
        tea.Teach();
    }
}

3. 继承核心规则(必记)

  • C# 单继承:一个子类只能有一个父类,一个父类可以有多个子类;

  • 继承只会复用 public/protected 成员,私有成员无法继承;

  • 子类可以扩展新功能,不会影响父类,实现代码拓展。

4. base 关键字:调用父类成员

子类可以通过 base 关键字,调用父类的属性、方法、构造函数,解决子类重写后无法使用父类逻辑的问题。

class Student : Person
{
    public int Score { get; set; }

    // 重写方法,同时保留父类逻辑
    public void StudentInfo()
    {
        // 调用父类的打招呼方法
        base.SayHello();
        Console.WriteLine($"我的考试成绩是:{Score}");
    }
}

四、面向对象核心:多态(Polymorphism)——代码灵活的核心

多态是三大特性中最抽象、但最实用的特性,核心作用:一个父类类型,适配多种子类对象,实现统一调用、不同表现,是项目解耦、框架开发的核心基础。

1. 多态实现条件(缺一不可)

  • 存在继承关系;

  • 父类定义 virtual 虚方法(允许被子类重写);

  • 子类使用 override 重写虚方法;

  • 父类引用指向子类对象。

2. 多态完整实战案例

using System;

// 父类
class Person
{
    // 虚方法:允许子类重写
    public virtual void ShowInfo()
    {
        Console.WriteLine("这是人类基础信息展示");
    }
}

// 学生子类:重写父类方法
class Student : Person
{
    public override void ShowInfo()
    {
        Console.WriteLine("我是学生,我的职责是认真学习!");
    }
}

// 老师子类:重写父类方法
class Teacher : Person
{
    public override void ShowInfo()
    {
        Console.WriteLine("我是老师,我的职责是教书育人!");
    }
}

class Program
{
    static void Main()
    {
        // 多态核心:父类引用 指向 子类对象
        Person p1 = new Student();
        Person p2 = new Teacher();

        // 统一调用方法,执行不同子类的逻辑
        p1.ShowInfo();
        p2.ShowInfo();
    }
}

3. 多态核心价值

不需要为每个子类单独写调用方法,统一父类接口,后续新增子类无需修改原有代码,完美符合程序设计的「开闭原则」,是大型项目架构的核心思想。

五、OOP三大特性整合实战(企业级小案例)

我们整合封装(属性)+ 继承 + 多态,完成一个完整可落地的案例,打通所有知识点:

using System;
using System.Collections.Generic;

// 父类:动物类
class Animal
{
    // 封装:自动属性
    public string Name { get; set; }
    public int Age { get; set; }

    // 虚方法,支持多态
    public virtual void Cry()
    {
        Console.WriteLine("动物发出叫声");
    }
}

// 子类:狗
class Dog : Animal
{
    public override void Cry()
    {
        Console.WriteLine($"{Name}{Age}岁):汪汪汪!");
    }
}

// 子类:猫
class Cat : Animal
{
    public override void Cry()
    {
        Console.WriteLine($"{Name}{Age}岁):喵喵喵!");
    }
}

class Program
{
    static void Main()
    {
        // 多态集合:统一存储所有子类对象
        List<Animal> animalList = new List<Animal>()
        {
            new Dog(){ Name = "旺财", Age = 2 },
            new Cat(){ Name = "橘猫", Age = 1 }
        };

        // 统一遍历调用,不同对象不同表现
        foreach (var animal in animalList)
        {
            animal.Cry();
        }
    }
}

六、新手高频易错坑点(必避)

  • 属性混淆:不要公开字段,自动属性用于常规封装,完整属性用于需要数据校验的场景;

  • 继承误区:C#不支持多类继承,私有成员无法被继承,子类只能拓展不能删减父类功能;

  • 多态报错:重写方法必须严格匹配 virtual+override,方法名、参数、返回值必须完全一致;

  • base滥用:仅需要保留父类逻辑时使用,避免代码冗余。

七、全文核心总结

  1. 属性是封装的现代化写法,替代冗余的Get/Set方法,保护数据安全,是C#项目开发唯一标准;

  2. 继承实现代码复用,通过父类抽取共性、子类拓展特性,简化层级代码;

  3. 多态实现统一接口、差异化执行,让代码更灵活、易扩展,适配复杂项目架构;

  4. 封装、继承、多态三位一体,构成C#面向对象编程的全部核心,是后续学习接口、泛型、框架开发的基础。

下期预告

下一篇我们将精讲 C# 静态类、静态成员、常量与只读,区分静态与实例的核心差异,解决新手分不清静态调用、实例调用的高频问题,进一步夯实项目开发基础!

更多推荐