一、抽象类 abstract class

1. 核心特点

  1. abstract 修饰,不能实例化,只能被继承
  2. 可包含:普通字段、普通方法、抽象方法(无方法体)、构造函数、属性
  3. 派生类必须重写所有抽象成员,用 override
  4. 单继承:一个类只能继承一个抽象类
  5. 有构造函数,子类实例化时会先执行父抽象类构造

示例代码

csharp

运行

// 抽象动物父类
abstract class Animal
{
    public string Name { get; set; }
    // 普通构造
    public Animal(string name)
    {
        Name = name;
    }
    // 抽象方法:无实现,子类必须重写
    public abstract void Speak();
    // 普通方法:已有实现,子类可重写可不重写
    public void Run()
    {
        Console.WriteLine($"{Name} 在奔跑");
    }
}

// 子类继承抽象类,重写抽象方法
class Dog : Animal
{
    public Dog(string name) : base(name) { }
    public override void Speak()
    {
        Console.WriteLine($"{Name}:汪汪汪");
    }
}

class Cat : Animal
{
    public Cat(string name) : base(name) { }
    public override void Speak()
    {
        Console.WriteLine($"{Name}:喵喵喵");
    }
}

二、接口 interface

1. 核心特点

  1. 关键字 interface不能实例化、无构造函数
  2. 只能包含:方法、属性、事件、索引器(不能有字段、普通变量
  3. 默认所有成员都是 public,不能加访问修饰符
  4. 一个类可实现多个接口(解决单继承局限)
  5. 接口成员必须全部实现,用 public 重写
  6. C#8.0+ 接口可以写默认实现方法

示例代码

csharp

运行

// 会叫的接口
interface ISpeak
{
    void Speak();
}
// 会飞的接口
interface IFly
{
    void Fly();
}

// 鸟类:同时实现两个接口
class Bird : ISpeak, IFly
{
    public void Speak()
    {
        Console.WriteLine("叽叽叽");
    }
    public void Fly()
    {
        Console.WriteLine("小鸟展翅飞翔");
    }
}

抽象类 vs 接口对比

表格

特性 抽象类 abstract 接口 interface
继承 / 实现 单继承 多实现
字段 可以有成员变量 不能有字段
构造函数
访问修饰 可 private/protected/public 只能 public
使用场景 提取子类公共代码、有共同属性行为 定义一套行为规范,多类不相关也可实现

三、多态 Polymorphism

1. 两种多态

  1. 编译时多态(静态):方法重载 Overload,同一个类同名不同参数
  2. 运行时多态(动态,核心):方法重写 Override,父类引用指向子类对象

动态多态核心规则

  • 父类变量 = new 子类 ();
  • 调用虚 / 抽象方法时,执行子类重写后的逻辑

多态完整演示(结合上面抽象类)

csharp

运行

class Program
{
    static void Main()
    {
        // 父类引用指向不同子类,多态体现
        Animal a1 = new Dog("旺财");
        Animal a2 = new Cat("橘猫");
        
        TestSpeak(a1);
        TestSpeak(a2);
    }

    // 统一接收父类,自动执行子类方法
    static void TestSpeak(Animal animal)
    {
        animal.Speak();
        animal.Run();
    }
}

输出:

plaintext

旺财:汪汪汪
旺财 在奔跑
橘猫:喵喵喵
橘猫 在奔跑

四、单向链表(手写基础链表)

链表核心:节点 Node + 链表管理类

  • 节点:存储数据 + 下一个节点地址
  • 链表:记录头节点,提供增删改查

完整单向链表代码

csharp

运行

// 链表节点
class Node<T>
{
    public T Data;         // 存储数据
    public Node<T> Next;   // 指向下一个节点
    public Node(T data)
    {
        Data = data;
        Next = null;
    }
}

// 泛型单向链表
class SingleLinkList<T>
{
    private Node<T> head; // 头节点
    public int Count { get; private set; } // 节点数量

    // 尾部添加
    public void Add(T data)
    {
        Node<T> newNode = new Node<T>(data);
        if (head == null)
        {
            head = newNode;
        }
        else
        {
            Node<T> temp = head;
            while (temp.Next != null)
            {
                temp = temp.Next;
            }
            temp.Next = newNode;
        }
        Count++;
    }

    // 遍历打印所有元素
    public void Show()
    {
        if (head == null)
        {
            Console.WriteLine("链表为空");
            return;
        }
        Node<T> temp = head;
        while (temp != null)
        {
            Console.Write(temp.Data + " ");
            temp = temp.Next;
        }
        Console.WriteLine();
    }

    // 根据值删除第一个匹配节点
    public void Remove(T data)
    {
        if (head == null) return;

        // 头节点就是目标
        if (head.Data.Equals(data))
        {
            head = head.Next;
            Count--;
            return;
        }

        Node<T> temp = head;
        // 找到待删节点的前一个
        while (temp.Next != null && !temp.Next.Data.Equals(data))
        {
            temp = temp.Next;
        }
        if (temp.Next == null) return;
        temp.Next = temp.Next.Next;
        Count--;
    }
}

// 测试
class Program
{
    static void Main()
    {
        SingleLinkList<int> list = new SingleLinkList<int>();
        list.Add(10);
        list.Add(20);
        list.Add(30);
        list.Show(); // 10 20 30

        list.Remove(20);
        list.Show(); // 10 30
        Console.WriteLine("节点总数:" + list.Count);
    }
}

五、综合拓展:接口 + 多态 + 链表结合思路

  1. 定义 IData 接口规范数据行为
  2. 多个实体类实现接口
  3. 链表存储接口类型,实现多态存放不同对象
  4. 遍历链表时自动调用各自重写的方法

更多推荐