【问题标题】:Use base classes implementation with correct access modifiers使用具有正确访问修饰符的基类实现
【发布时间】:2026-02-09 20:00:02
【问题描述】:

我想要一个名为IProblem 的问题的接口。有两种方法:Solve() 和 CheckArguments()。 Problem 类将实现 CheckArguments() 函数,因为它对于所有问题都是相同的。但是后来我遇到了不同类型的问题,例如EasyProblemHardProblem,它们具有 Solve() 方法的不同实现,但 CheckArguments() 方法总是相同的,我总是想使用基类 Problem() 的实现.

我想要正确的修饰符,但我对在哪个类/接口中定义哪个方法有点困惑。更何况我还有一个针对这两个功能的测试项目。

【问题讨论】:

  • 你能展示你的类/界面吗?这将有助于理解需求和问题。

标签: c# .net oop inheritance


【解决方案1】:

我不确定您的问题是否是“使用什么”,但我建议使用接口和抽象类:

public interface IProblem {
    void Solve();
    void CheckArguments();
}

public abstract class Problem : IProblem {
    public abstract void Solve();
    public void CheckArguments() {
        ...
    }
}

public class EasyProblem : Problem
{
    public override void Solve()
    {
        ....
    }
}

这样,检查参数在基类中实现,所有派生类都实现 IProblem,每个派生类都必须实现 Solve。

如果您省略接口并且只支持派生自 Problem 的类,您将确保给定的类不能提供自己的 CheckArguments() 实现。

public abstract class Problem {
    public abstract void Solve();
    public void CheckArguments() {
        ...
    }
}

public class EasyProblem : Problem
{
    public override void Solve()
    {
        ....
    }
}

...
static Main(string[] args)
{
    List<Problem> problemsToSolve = ...
    foreach(var problem in problemsToSolve)
    {
        problem.CheckArguments();
        problem.Solve();
    }
}    

【讨论】:

    【解决方案2】:

    你可以试试:

    public interface ISupportArguments
    {
       bool CheckArguments();
    }
    
    public abstract class AbstractProblem : ISupportArguments
    {
       public bool CheckArguments() {
            return true;
       }
    
       public abstract void SolveProblem();
    }
    

    所以你的每个类都派生自 AbstractProblem 并覆盖 它自己的版本

    SolveProblem(..)
    

    【讨论】:

      【解决方案3】:

      Matten已经很好地展示了类结构。
      关于访问修饰符:我会提出一种防御方法,以便您使用最严格的访问修饰符来解决问题。事后减少限制比限制更多更容易,因为您可能必须向您的代码的某些用户解释为什么他们不能再使用它。

      因此对于类型(接口和类):如果您在其他程序集中不需要它们,请将它们定义为内部。如果您想从您的测试项目中访问这些类型,您可以使用InternalsVisibleTo 属性来从特定程序集中访问它们。您将属性添加到包含类型的程序集,并提供测试程序集的名称(以及对于强命名程序集的一些附加数据)作为参数。

      这同样适用于成员。也可以考虑实现接口explicitly,这样只有通过接口访问类才能访问方法。

      【讨论】:

        最近更新 更多