【问题标题】:Generic type parameters at two levels of inheritance两个继承级别的泛型类型参数
【发布时间】:2018-03-04 22:24:34
【问题描述】:

我有一个用于运行各种测试的测试仪器及其设置的基类:

// these classes need to stay as-is
abstract class XmlSettings { }
abstract class TestInstrument<T> where T : XmlSettings { }

在一个简单的例子中,一个TestInstrument声明如下

sealed class LivSettings : XmlSettings { }
sealed class Liv : TestInstrument<LivSettings> { }

但是我有一个案例,其中一些测试工具有很多共同点,除了一个从其他基类派生的属性。此属性是一种激光。这是一个例子

// base class of lasers
abstract class LaserBase { }
// two types of lasers
sealed class Engine : LaserBase { }
sealed class Blade : LaserBase { }
// base class for laser calibration test instrument. <XmlSettings> needs to be narrowed based on type of laser
abstract class LaserCalibrationBase<T> : TestInstrument<XmlSettings> where T : LaserBase { }
// settings class for each type of laser
sealed class EngineCalibrationSettings : XmlSettings { };
sealed class BladeCalibrationSettings : XmlSettings { };
// calibration class for each type of laser
sealed class EngineCalibration : LaserCalibrationBase<Engine> { }
sealed class BladeCalibration : LaserCalibrationBase<Blade> { }

请注意,这会编译,但是我无法指定EngineCalibrationSettingsBladeCalibrationSettings,然后我在TestInstrument&lt;XmlSettings&gt; 中使用XmlSettings 代替它们。这是不对的,因为我必须将 XmlSettings 缩小到适当的设置类。

我猜需要解决可能的重复问题。我不能使用两个接口,因为每个抽象类也有带有具体实现的虚方法。

【问题讨论】:

  • @Kitson88 不完全是,因为两个基类也都有具体的方法。我应该提到这一点。
  • 抱歉,如果我误解了,但我只能看到你试图从一个具体类继承两个抽象类。如果是这种情况,那么我建议考虑将LaserCalibrationBase&lt;T&gt;TestInstrument&lt;T&gt; 合并到最终强制派生类型实现的接口。您可以继承任意数量的接口。
  • @Kitson88 每个抽象类里面都有很多实现。否则它们可能是接口。如果 TestInstrument 没有泛型类型参数,就没有问题。那是我的旧设计,但我想添加通用 SettingsClass 以增加更多自动化。曾经是 BladeCalibration : LaserCalibrationBase 和 LaserCalibrationBase : TestInstrument。这就是 BladeCalibration 继承 TestInstrument 的方式
  • 有一个继承链。我并不是真的在寻找多重继承。我打算这样做 BladeCalibration : LaserCalibration : TestInstrument,但是在多个级别上都需要泛型类型参数。我通过删除一个泛型类型参数来解决它,因此它只需要在最高继承级别。

标签: c# generics inheritance


【解决方案1】:

我目前使用的一种解决方法是只为所有类型的激光设置一个设置类

// base class of lasers
abstract class LaserBase { }
// two types of lasers
sealed class Engine : LaserBase { }
sealed class Blade : LaserBase { }
// base class for laser calibration test instrument. All laser types will use LaserCalibrationSettings
abstract class LaserCalibrationBase<T> : TestInstrument<LaserCalibrationSettings> where T : LaserBase { }
// settings class for all lasers
sealed class LaserCalibrationSettings : XmlSettings { };
// calibration class for each type of laser
sealed class EngineCalibration : LaserCalibrationBase<Engine> { }
sealed class BladeCalibration : LaserCalibrationBase<Blade> { }

这是可行的,因为设置类是从 xml 反序列化的。我可以选择仅在每个设置对象中包含与每种激光类型相对应的设置,其他属性不会被校准类使用(但可用,这是不可取的)

<LaserCalibrationSettings>
  <BladeName>Blade 1</BladeName>
  <!-- other settings -->
</LaserCalibrationSettings>
<LaserCalibrationSettings>
  <EngineName>Engine 1</EngineName>
  <!-- other settings -->
</LaserCalibrationSettings>

和(在 vb.net 中)

Public Class LaserCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property BladeName As String
    <XmlElement>
    Public Property EngineName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

对比什么更可取

<EngineCalibrationSettings>
  <EngineName>Engine 1</EngineName>
  <!-- other settings -->
</EngineCalibrationSettings>
<BladeCalibrationSettings>
  <BladeName>Blade 1</BladeName>
  <!-- other settings -->
</BladeCalibrationSettings>

Public Class BladeCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property BladeName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

Public Class EngineCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property EngineName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

不希望的是,例如在 EngineCalibration 中,我可以访问不适用的 BladeName,即

sealed class EngineCalibration : LaserCalibrationBase<Engine>
{
    public void Run()
    {
        Console.WriteLine(this.Settings.BladeName); // N/A!
    }
}

这就是为什么它只是一种解决方法。

【讨论】:

    猜你喜欢
    • 2012-11-29
    • 2015-11-18
    • 1970-01-01
    • 2018-09-27
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    相关资源
    最近更新 更多