C# 继承
单继承、`base`、构造链、`virtual`/`override`/`new`、抽象类。
Key PointsC# 只支持单继承(一个父类),但可以实现多个接口。
基本继承
C#
class Shape
{
public string Name { get; set; } = "图形";
public virtual double Area() => 0;
public override string ToString() => $"{Name} 面积 {Area():F2}";
}
class Circle : Shape
{
public double Radius { get; set; }
public Circle() { Name = "圆"; }
public override double Area() => Math.PI * Radius * Radius;
}
class Rect : Shape
{
public double W { get; set; }
public double H { get; set; }
public Rect() { Name = "矩形"; }
public override double Area() => W * H;
}
Console.WriteLine(new Circle { Radius = 1 });
Console.WriteLine(new Rect { W = 3, H = 4 });Output
圆 面积 3.14
矩形 面积 12.00构造链与 base
C#
class Animal
{
public string Name { get; }
public Animal(string name)
{
Name = name;
Console.WriteLine($"Animal 构造:{name}");
}
}
class Dog : Animal
{
public string Breed { get; }
// 先调用父类构造,再执行自己的
public Dog(string name, string breed) : base(name)
{
Breed = breed;
Console.WriteLine($"Dog 构造:{breed}");
}
}
var d = new Dog("旺财", "柴犬");
Console.WriteLine($"{d.Name} {d.Breed}");Output
Animal 构造:旺财
Dog 构造:柴犬
旺财 柴犬Construction order is always base first, derived second. If the base has no parameterless constructor, the derived class must call : base(...) or it will not compile.
virtual / override / new
C#
class Base
{
public virtual string Who() => "Base";
public string Fixed() => "Base.Fixed";
}
class Derived : Base
{
public override string Who() => "Derived"; // 重写
public new string Fixed() => "Derived.Fixed"; // 隐藏(不推荐)
}
Base b = new Derived();
Console.WriteLine(b.Who()); // 多态:Derived
Console.WriteLine(b.Fixed()); // 非虚:Base.Fixed
Derived d = new Derived();
Console.WriteLine(d.Fixed()); // Derived.FixedOutput
Derived
Base.Fixed
Derived.Fixednew only shadows a name: calls through a base reference still hit the base version. It is almost always a bug. When the compiler warns hides inherited member, reach for override.抽象类
C#
abstract class Employee
{
public string Name { get; set; } = "";
// 抽象方法:子类必须实现
public abstract decimal Salary();
// 模板方法:定义骨架,调用抽象方法
public string Report() => $"{Name} 月薪 {Salary():C}";
}
class FullTime : Employee
{
public decimal Monthly { get; set; }
public override decimal Salary() => Monthly;
}
class PartTime : Employee
{
public decimal Hourly { get; set; }
public int Hours { get; set; }
public override decimal Salary() => Hourly * Hours;
}
Employee[] staff = { new FullTime { Name = "张三", Monthly = 12000m }, new PartTime { Name = "李四", Hourly = 80m, Hours = 100 } };
foreach (var e in staff) Console.WriteLine(e.Report());Output
张三 月薪 ¥12,000.00
李四 月薪 ¥8,000.00继承 vs 组合
| Use inheritance when | Use composition when |
|---|---|
| 确实是「是一种」(Dog 是 Animal) | 只是「有一个」(Car 有 Engine) |
| 需要父类的多态行为 | 只想复用实现 |
| 层级稳定、不会频繁加子类 | 行为需要运行时组合 |
C# allows only single inheritance, so "reuse both implementations" hits a wall immediately. Extract interfaces plus composed members instead of forcing a hierarchy.
基本继承
C#
class Shape
{
public string Name { get; set; } = "图形";
public virtual double Area() => 0;
public override string ToString() => $"{Name} 面积 {Area():F2}";
}
class Circle : Shape
{
public double Radius { get; set; }
public Circle() { Name = "圆"; }
public override double Area() => Math.PI * Radius * Radius;
}
class Rect : Shape
{
public double W { get; set; }
public double H { get; set; }
public Rect() { Name = "矩形"; }
public override double Area() => W * H;
}
Console.WriteLine(new Circle { Radius = 1 });
Console.WriteLine(new Rect { W = 3, H = 4 });Output
圆 面积 3.14
矩形 面积 12.00构造链与 base
C#
class Animal
{
public string Name { get; }
public Animal(string name)
{
Name = name;
Console.WriteLine($"Animal 构造:{name}");
}
}
class Dog : Animal
{
public string Breed { get; }
// 先调用父类构造,再执行自己的
public Dog(string name, string breed) : base(name)
{
Breed = breed;
Console.WriteLine($"Dog 构造:{breed}");
}
}
var d = new Dog("旺财", "柴犬");
Console.WriteLine($"{d.Name} {d.Breed}");Output
Animal 构造:旺财
Dog 构造:柴犬
旺财 柴犬构造顺序永远是父类先、子类后。如果父类没有无参构造,子类必须用 : base(...) 显式调用,否则编译失败。
virtual / override / new
C#
class Base
{
public virtual string Who() => "Base";
public string Fixed() => "Base.Fixed";
}
class Derived : Base
{
public override string Who() => "Derived"; // 重写
public new string Fixed() => "Derived.Fixed"; // 隐藏(不推荐)
}
Base b = new Derived();
Console.WriteLine(b.Who()); // 多态:Derived
Console.WriteLine(b.Fixed()); // 非虚:Base.Fixed
Derived d = new Derived();
Console.WriteLine(d.Fixed()); // Derived.FixedOutput
Derived
Base.Fixed
Derived.Fixednew 隐藏方法只是「同名遮蔽」,通过父类引用调用时仍走父类版本。它几乎总是 bug 而不是设计——除非你明确知道自己在做什么,否则看到编译器提示 hides inherited member 就加 override。抽象类
C#
abstract class Employee
{
public string Name { get; set; } = "";
// 抽象方法:子类必须实现
public abstract decimal Salary();
// 模板方法:定义骨架,调用抽象方法
public string Report() => $"{Name} 月薪 {Salary():C}";
}
class FullTime : Employee
{
public decimal Monthly { get; set; }
public override decimal Salary() => Monthly;
}
class PartTime : Employee
{
public decimal Hourly { get; set; }
public int Hours { get; set; }
public override decimal Salary() => Hourly * Hours;
}
Employee[] staff = { new FullTime { Name = "张三", Monthly = 12000m }, new PartTime { Name = "李四", Hourly = 80m, Hours = 100 } };
foreach (var e in staff) Console.WriteLine(e.Report());Output
张三 月薪 ¥12,000.00
李四 月薪 ¥8,000.00继承 vs 组合
| 用继承当 | 用组合当 |
|---|---|
| 确实是「是一种」(Dog 是 Animal) | 只是「有一个」(Car 有 Engine) |
| 需要父类的多态行为 | 只想复用实现 |
| 层级稳定、不会频繁加子类 | 行为需要运行时组合 |
C# 只能单继承,所以「想复用两边的实现」时继承会立刻卡住。这时把公共部分抽成接口 + 组合的成员,比硬凑继承层级更好维护。