使用抽象父类引用子类时的子类属性设置方案咨询
最佳解决方案
方案1:用C#类型模式匹配(最简改法)
直接在Value2Changed里做类型判断,不用改动原有类结构,代码改动最小:
public void Value2Changed(string newValue) { if (client is ClientV3 clientV3) { clientV3.Value2 = newValue; } }
后续新增ClientV4时,只需在需要处理其特有属性的方法里新增对应类型判断分支即可,不会影响现有逻辑。
方案2:拆接口解耦(符合开闭原则)
如果希望代码结构更规整,可针对子类的特有属性单独定义接口:
- 新增对应属性接口:
public interface IHasValue2 { string Value2 { get; set; } }
- 让
ClientV3实现该接口:
public class ClientV3 : Client, IHasValue2 { public string Value2 { get; set; } public string Value3 { get; set; } // 实现Send和Get方法 }
- 修改Program类的属性设置方法:
public void Value2Changed(string newValue) { if (client is IHasValue2 hasValue2) { hasValue2.Value2 = newValue; } }
后续新增ClientV4时,若它有类似Value4的特有属性,只需新增IHasValue4接口并让ClientV4实现,对应属性处理方法照此逻辑扩展即可,无需修改原有抽象类和其他子类。
方案3:访客模式(复杂场景首选)
如果子类特有属性较多,且后续会频繁新增子类,可使用访客模式彻底解耦类型依赖:
- 定义访客接口:
public interface IClientVisitor { void Visit(ClientV2 client); void Visit(ClientV3 client); // 新增子类时添加对应的Visit方法 }
- 为抽象类
Client添加接受访客的方法:
public abstract class Client { public abstract void Send(); public abstract void Get(); public abstract void Accept(IClientVisitor visitor); }
- 每个子类实现
Accept方法:
public class ClientV2 : Client { public string Value1 {get;set;} public override void Accept(IClientVisitor visitor) { visitor.Visit(this); } // 实现Send和Get方法 } public class ClientV3 : Client { public string Value2 {get;set;} public string Value3 {get;set;} public override void Accept(IClientVisitor visitor) { visitor.Visit(this); } // 实现Send和Get方法 }
- 在Program中实现访客类处理属性设置:
public class ClientPropertySetter : IClientVisitor { public string NewValue2 { get; set; } public void Visit(ClientV2 client) { // 无需处理ClientV2则留空实现 } public void Visit(ClientV3 client) { client.Value2 = NewValue2; } } // 修改Value2Changed方法 public void Value2Changed(string newValue) { var setter = new ClientPropertySetter { NewValue2 = newValue }; client.Accept(setter); }
后续新增ClientV4时,只需在IClientVisitor中添加对应Visit方法、让ClientV4实现Accept,再在访客类中编写属性处理逻辑即可,Program的核心代码无需改动。
内容的提问来源于stack exchange,提问作者karol kole
相关产品推荐
相关产品推荐

