如何让同基类的多个partial类功能被新同基类类调用?
我懂你现在的困境啦——手里一堆继承自FruitHandler(实际是Form)的partial清洗类,每个都藏着自己的水果清洗方法,现在要做个同样继承FruitHandler的FruitEater,得根据水果类型调用对应的清洗方法,但目前的写法不仅碰不到私有清洗方法,还堆了一堆if-else,既不优雅也难维护。下面给你几个实用的重构思路,都能满足所有类基类必须是FruitHandler的要求:
第一步:先解决访问权限问题
原来的CleanApple、CleanPear这些方法都是private的,FruitEater作为兄弟类根本访问不到。最简单的办法是把这些方法的访问修饰符改成internal(如果所有类在同一个程序集里)或者public。比如:
public partial class AppleCleaner : FruitHandler { public AppleCleaner(int fruitSize) { CleanApple(fruitSize); } // 改成internal让同程序集的FruitEater能访问 internal void CleanApple(int size) { // 苹果清洗逻辑 } }
方案一:用字典映射+接口实现类型安全的调用
这种方式能彻底干掉if-else,而且后续新增水果只需要加新的类和映射,不用改FruitEater的核心逻辑:
- 先定义一个清洗接口,统一清洗方法的签名:
public interface IFruitCleaner { void Clean(int size); }
- 让每个清洗类实现这个接口(把原有私有方法包装一下):
public partial class AppleCleaner : FruitHandler, IFruitCleaner { public AppleCleaner(int fruitSize) { Clean(fruitSize); } // 实现接口方法,内部调用原有清洗逻辑 void IFruitCleaner.Clean(int size) { CleanApple(size); } void CleanApple(int size) { // 苹果清洗逻辑 } }
- 最后在FruitEater里用字典做水果类型到清洗器的映射,直接调用接口方法:
public partial class FruitEater : FruitHandler { // 提前把水果和对应的清洗器工厂映射好 private static readonly Dictionary<string, Func<int, IFruitCleaner>> _cleanerMap = new() { {"Apple", size => new AppleCleaner(size)}, {"Pear", size => new PearCleaner(size)}, {"Banana", size => new BananaCleaner(size)} }; public FruitEater(Fruit fruit) { if (_cleanerMap.TryGetValue(fruit.Name, out var createCleaner)) { var cleaner = createCleaner(fruit.size); cleaner.Clean(fruit.size); } EatFruit(fruit); } void EatFruit(Fruit fruit) { // 吃水果的逻辑 } }
方案二:把清洗逻辑抽离到独立服务类(更适合Form场景)
考虑到实际场景中FruitHandler是Form类,窗体类应该专注于UI逻辑,把清洗这种业务逻辑抽离出来会更合理:
- 新建一个专门的清洗服务类,把所有清洗逻辑集中在这里:
public static class FruitCleaningService { public static void CleanApple(int size) { // 苹果清洗逻辑 } public static void CleanPear(int size) { // 梨子清洗逻辑 } public static void CleanBanana(int size) { // 香蕉清洗逻辑 } // 统一的清洗入口,用switch替代if-else更清晰 public static void CleanFruit(Fruit fruit) { switch(fruit.Name) { case "Apple": CleanApple(fruit.size); break; case "Pear": CleanPear(fruit.size); break; case "Banana": CleanBanana(fruit.size); break; default: throw new ArgumentException($"不认识的水果:{fruit.Name}"); } } }
- 原来的清洗窗体类简化成调用服务:
public partial class AppleCleaner : FruitHandler { public AppleCleaner(int fruitSize) { FruitCleaningService.CleanApple(fruitSize); } }
- FruitEater里直接调用服务的统一方法,代码超简洁:
public partial class FruitEater : FruitHandler { public FruitEater(Fruit fruit) { FruitCleaningService.CleanFruit(fruit); EatFruit(fruit); } void EatFruit(Fruit fruit) { // 吃水果的逻辑 } }
这个方案的好处是把业务逻辑和UI彻底解耦,后续维护清洗逻辑不用碰窗体代码,新增水果只需要在服务类里加方法和switch分支就行。
内容的提问来源于stack exchange,提问作者TJ_
相关产品推荐
相关产品推荐

