在实现中接受缩小类型的MustOverride方法的正确模式

时间:2013-07-10 21:53:51

标签: .net vb.net inheritance override

我正在编写一些软件,可以自动从实验中收集数据,并需要一些帮助来表达我的业务对象之间的关系。

我有一个名为Experiment的类型,一个名为Sample的类型,以及RunOnSample中未实现的Experiment方法,它应该接受Sample的派生输入数据并填入其中:

Public MustInherit Class Experiment
    Public Property TestDate As Date
    Public Property Experimenter As String

    Public MustOverride Sub RunOnSample(sample As Sample)
End Class

Public MustInherit Class Sample
    Public Property UnitLotCode As String
End Class

这些类型都不是实际可实例化的,因为我有不同的实验(由Experiment的子类型表示),它们生成各种数据。每个实验都有一个匹配的Sample子类型,该子类型具有存储实验生成的数据的属性。请注意,基类是必要的,因为所有实验都有一些共同的属性,以及将为所有样本记录的一些数据。

例如,ThicknessExperiment测量厚度数据并扫描大量代码,然后将此数据填入ThicknessSample

Public Class ThicknessExperiment
    Public Overrides Sub RunOnSample(sample As ThicknessSample)
        Dim data = GetDataFromMeasurementDevice()

        sample.UnitLotCode = data.LotCode
        sample.Thickness = data.Thickness
    End Sub
End Class

Public MustInherit Class ThicknessSample
    Public Property Thickness As Single
End Class

这里的问题是参数的类型对编译器是不可接受的; RunOnSample的实施必须接受Sample,而不是ThicknessSample(或Sample的任何其他子类型)。大概这是因为,如果编译器让我按照自己的方式进行,派生的实验将不再具有与父类相同的接口,这将是非多态的。

我能想到解决这个问题的唯一方法是在使用之前将参数转换为方法内的Sample的相应子类型。有没有更好的方法来实现我的目标?最好是一种维护XYZExperiment.RunOnSample方法与XYZSample参数的强类型关联的方法吗?

1 个答案:

答案 0 :(得分:1)

首先,我想说,作为一个个人偏好一点经验我学会了不使用继承代码重用或公共属性,但是只是为了从多态中受益,所以我将这些公共数据属性提取到一个新类中,并使用字典表示不同的属性,然后使用委托(组合)来存储某个样本的数据。无论如何,我建议的解决方案涉及使用泛型,所以你可以做这样的事情:

public abstract class Experiment<TSample>
            where TSample : Sample
        {
            private DateTime experimentDate;
            private string Experimenter;

            public abstract void RunOnSample(TSample sample);
        }

        public class ThicknessExperiment : Experiment<ThicknessSample>
        {

            public override void RunOnSample(ThicknessSample sample)
            {
                // sample.lotcode = "43";
                // sample.data1 = "343";
                // sample.data2 = "43";

            }
        }

        public abstract class Sample
        {
            public string lotcode;

        }

        public class ThicknessSample : Sample
        {
            public string data1;
            public string data2;
        }