有多个相同但名称不同的类是否合适?

本文关键字:是否 | 更新日期: 2023-09-27 17:53:02

我有一个关于命名多个共享相似功能的类的问题。我正在研究一个科学的API,并有以下类/接口:

public interface IRange<T>{
    T Minimum {get;}
    T Maximum {get;}
    // A few other methods that aren't important
}
public class Range<T> : IRange<T> where T: IComparable<T> {
    public T Minimum {get; protected set;}
    public T Maximum {get; protected set;}
    public Range(T minimum, T maximum) {
        Minimum = minimum;
        Maximum = maximum;
    }
}

对于我的API,我经常使用double范围(即Range<double>),因此我创建了另一个名为MassRange的类。这个类还有一些新的构造函数和属性,如下所示:

public class MassRange : Range<double>, IRange<double> {
    public double Width { get { return Maximum - Minimum;} }
    public double Mean { get { return (Maximum + Minimum) / 2.0;} }
    public MassRange(double mean, MassTolerance width) {
        Minimum = mean - width.Value;  // pseudo-code
        Maximum = mean + width.Value;
    }
}

从概念上讲,我还有另一种类型的Range<double>称为MzRange,它与MassRange共享所有相同的结构和功能,但我想在API中保持分离。它们的行为完全相同,存储的数据类型也相同,但就科学而言,它们是不同的、截然不同的。

所以我考虑将MassRange类重命名为DoubleRange的更通用的名称,然后将MassRange : DoubleRangeMzRange : DoubleRange设计成这样:

public MzRange : DoubleRange, IRange<double> {}
public MassRange : DoubleRange, IRange<double> {}

但是我真的不关心DoubleRange这个名字,并且宁愿不通过我的API公开它。公开两个具有相同功能的不同类型是否合适?我是否应该为DoubleRange取一个更好的名字,而放弃MzRangeMassRange ?我可以使DoubleRange内部或其他东西,使它不通过API暴露,但仍然可以使用?

这似乎是一个案例的扩展属性,但我知道他们目前不存在。

有多个相同但名称不同的类是否合适?

似乎没有任何理由不能使用标准扩展方法完成此任务:

public static double GetWidth(this IRange<double> range) {
    return range.Maximum - range.Minimum;
}
public static double GetMean(this IRange<double> range) {
    return (range.Maximum + range.Minimum) / 2.0;
}

然后你可以从IRange的任何实现中调用它:

var massRange = ...
var mean = massRange.GetMean();

我知道它可能没有扩展属性的语法吸引力,但它是一个干净的解决方案,可以绕过必须创建DoubleRange类。

这是绝对合适的。除了逻辑上的区别之外,它还使您有可能在将来独立地发展这两个类。

即使大象和鸟都是动物(都继承自动物),并且都有相同的属性集(它们不添加或覆盖成员),您可能希望将来为鸟类添加Fly方法。我假设在现实世界场景中不存在名为Dumbo的大象:-)

让两种类型具有完全相同的功能是不合适的,因为对一种类型的任何更改都需要对另一种类型进行更改。

除非您知道将来某个时候MassRangeMzRange会被区分开来,否则为DoubleRange提供一个更好的名称而放弃MassRange/MzRange是可行的方法。即使这样,任何共享的功能都需要放在父类型中。

你总是可以提供一些语法糖来帮助用户。例如,您可以创建名为MassRangeMzRange的"哑"类,它们只是扩展DoubleRange。我将保留原始的、命名良好的类,以鼓励用户使用它,但如果您真的想隐藏它,只需使用protected访问器而不是public