C# OOP开发中与对象相关的字段应定义在基类还是派生类中
C# 抽象基类公共属性设计方案
核心结论:你当前场景下所有动物子类都需要名称属性,应该将其定义在抽象基类Animal中,不要在各个派生类重复定义,这是OOP继承特性的标准使用方式。
- 降低代码冗余:所有子类共有的属性逻辑统一放在基类,后续需要调整名称的校验、格式化等逻辑时,只需要修改基类一处即可,不需要遍历所有子类逐一调整。
- 符合抽象原则:
Animal是对所有动物的抽象,「拥有名称」是所有动物的通用特征,这个属性的归属天然属于基类层级,不属于某个具体的子类。
注意不要直接定义protected字段,C#规范更推荐用属性封装成员,哪怕是仅对派生类开放的成员也尽量用属性实现,方便后续扩展逻辑时不破坏继承结构
普通场景的标准实现示例:
public abstract class Animal { // 对外公开get访问器,仅允许基类和派生类修改名称 public string AnimalName { get; protected set; } // 基类定义构造函数,强制所有派生类初始化时必须传入动物名称 protected Animal(string animalName) { // 可以在这里统一添加名称的校验逻辑 if (string.IsNullOrWhiteSpace(animalName)) throw new ArgumentException("动物名称不能为空", nameof(animalName)); AnimalName = animalName; } } // 派生类实现 public class Pig : Animal { public Pig(string name) : base(name) { // 派生类自身的初始化逻辑 } }
如果不同子类的名称生成/获取逻辑差异极大,基类完全无法提供统一实现,才考虑定义抽象属性要求子类实现:
public abstract class Animal { // 抽象属性,强制所有子类自行实现名称的获取逻辑 public abstract string AnimalName { get; } } public class Pig : Animal { private readonly string _name; public override string AnimalName => _name; public Pig(string name) { _name = name; } }
约定俗成的通用规范
- 所有子类共有的成员,优先放到基类实现,避免重复代码
- 仅当不同子类的同一名义成员逻辑差异极大,基层无法提供公共实现时,才使用抽象成员要求子类自行实现
- C#中禁止直接对外或者对派生类暴露字段,统一用属性封装成员,方便后续添加校验、触发事件等扩展逻辑而不修改继承链的调用代码
内容的提问来源于stack exchange,提问作者Gareth Westwood
相关产品推荐
相关产品推荐

