You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让同基类的多个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的核心逻辑:

  1. 先定义一个清洗接口,统一清洗方法的签名:
public interface IFruitCleaner
{
    void Clean(int size);
}
  1. 让每个清洗类实现这个接口(把原有私有方法包装一下):
public partial class AppleCleaner : FruitHandler, IFruitCleaner
{ 
    public AppleCleaner(int fruitSize) 
    { 
        Clean(fruitSize); 
    } 

    // 实现接口方法,内部调用原有清洗逻辑
    void IFruitCleaner.Clean(int size)
    {
        CleanApple(size);
    }

    void CleanApple(int size) 
    { 
        // 苹果清洗逻辑
    } 
}
  1. 最后在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逻辑,把清洗这种业务逻辑抽离出来会更合理:

  1. 新建一个专门的清洗服务类,把所有清洗逻辑集中在这里:
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}");
        }
    }
}
  1. 原来的清洗窗体类简化成调用服务:
public partial class AppleCleaner : FruitHandler 
{ 
    public AppleCleaner(int fruitSize) 
    { 
        FruitCleaningService.CleanApple(fruitSize); 
    } 
}
  1. FruitEater里直接调用服务的统一方法,代码超简洁:
public partial class FruitEater : FruitHandler 
{
    public FruitEater(Fruit fruit) 
    {
        FruitCleaningService.CleanFruit(fruit);
        EatFruit(fruit); 
    } 

    void EatFruit(Fruit fruit) 
    { 
        // 吃水果的逻辑
    } 
}

这个方案的好处是把业务逻辑和UI彻底解耦,后续维护清洗逻辑不用碰窗体代码,新增水果只需要在服务类里加方法和switch分支就行。

内容的提问来源于stack exchange,提问作者TJ_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:01:18