3

我写了这个例子来帮助解释。如您所见,我有一个对象层次结构。我想修改 GetFeatures() 函数以仅返回由我实例化的对象类型的构造函数添加的功能。例如,BasicModel.GetFeatures(new LuxuryModel()) 应该只返回特征“Leather Seats”和“Sunroof”。如果必须,我不介意使用反射。

Public Class Feature

    Public Sub New(ByVal model As BasicModel, ByVal description As String)
        _model = model
        _description = description
    End Sub

    Private _model As BasicModel
    Public Property Model() As BasicModel
        Get
            Return _model
        End Get
        Set(ByVal value As BasicModel)
            _model = value
        End Set
    End Property

    Private _description As String
    Public Property Description() As String
        Get
            Return _description
        End Get
        Set(ByVal value As String)
            _description = value
        End Set
    End Property

End Class


Public Class BasicModel
    Public Sub New()
        _features = New List(Of Feature)
    End Sub

    Private _features As List(Of Feature)

    Public ReadOnly Property Features() As List(Of Feature)
        Get
            Return _features
        End Get
    End Property

    Public Shared Function GetFeatures(ByVal model As BasicModel) As List(Of Feature)
        'I know this is wrong, but something like this...'
        Return model.Features.FindAll(Function(f) f.Model.GetType() Is model.GetType())
    End Function
End Class


Public Class SedanModel
    Inherits BasicModel

    Public Sub New()
        MyBase.New()
        Features.Add(New Feature(Me, "Fuzzy Dice"))
        Features.Add(New Feature(Me, "Tree Air Freshener"))
    End Sub
End Class


Public Class LuxuryModel
    Inherits SedanModel

    Public Sub New()
        MyBase.New()
        Features.Add(New Feature(Me, "Leather Seats"))
        Features.Add(New Feature(Me, "Sunroof"))
    End Sub
End Class
4

5 回答 5

1

如果要保留当前的层次结构/属性,只需创建基类的实例并从派生类中的特征中减去基类中的特征。

或者,您可能需要考虑稍微更改您的类层次结构,以使您自己更轻松。

例如,您可以将 Features 属性拆分为两个属性,例如 ModelFeatures 和 AllFeatures。

ModelFeatures 特定于当前模型(LuxuryModel 的“Leather Seats”和“Sunroof”等)AllFeatures 返回 MyBase.AllFeatures 和 ModelFeatures 的联合。这使得获取当前模型的特性成为一个微不足道的属性访问。

PS 请原谅我的 VB 错误,C# 是我的首选语言。

于 2009-06-12T23:12:10.467 回答
1

我对 VB.NET 语法并不熟悉,所以这里是应该工作的 C# 语法:

public IList<Function> GetFeatures(BasicModel model)
{
    return model.Features.Where(f => f.Model.GetType() == model.GetType()).ToList();
}
于 2009-06-12T23:16:03.873 回答
1

(基于您上面的示例代码)

老实说,我认为这不属于您的 Car Heirachy,在我看来,您希望获取静态数据并使用您的基类作为它的容器,并将您的后代类型作为键。正如您所看到的,这会导致一些简单的代码变得笨拙或过于复杂。

我更倾向于将您的静态数据放在它所属的位置,(在这种情况下)与 Feature 类本身。我不是一个 VB 人,所以这个 C# 中的代码片段。

所以在 Feature 类本身中,有一个静态属性(或方法)

public static IEnumerable<Feature> GetLuxuryFeatureSets
{
  get
  {
    yield return new Feature() { Name = "Leather Seats" };
    yield return new Feature() { Name = "Sunroof" };
  }
}

并为您的其他模型重复。因此,现在您有了一个有意义的静态数据容器,即类本身。

于 2009-06-12T23:38:01.480 回答
1

由于无法区分一个特征和另一个特征,您需要能够询问模型它添加了哪些特征。与其在构造函​​数中将功能添加到列表中,不如使用一个方法返回特定模型添加的功能列表...

public class LuxuryModel
{
  public LuxuryModel
  {
     Features.Add( GetFeatures() );
  }
  public List<Features> GetFeatures()
  {
     return new List<Features>( /* new up leather and whatever */
  }
}

然后,GetFeatures 可以进行向下转换并询问给定实例以获取该特定实例添加的功能列表......

public List<Features> GetFeatures<T>( BasicModel model )
{
   var m = Model as T;
   return m.GetFeatures();
}
于 2009-06-12T23:39:01.977 回答
1

如果您不希望此数据是静态的(请参阅我的另一个答案),并且您希望它可以扩展到新类,并让这些类控制功能集,那么另一种方法是这样做。然后使用多态性(再次使用 C#,因为我不是 VB 人)

在您的基类中创建一个返回功能的虚拟方法,在您的正统类中覆盖该属性,多态性允许您的变量作为基本模型类型,只要它们被构造为后代类型以返回正确的列表。

  public class BasicModel
  {
    public virtual IEnumerable<Feature> GetFeatures 
    {
      get
      {
        throw new NotImplementedException();
      }
    }
  }


  public class LuxuryModel :BasicModel
  {
    public override IEnumerable<Feature> GetFeatures
    {
      get
      {
        yield return new Feature() { Name = "Leather Seats" };
        yield return new Feature() { Name = "Sunroof" };
      }
    }
  }



private void button1_Click(object sender, EventArgs e)
{
  StringBuilder sb = new StringBuilder();

  BasicModel bm = new LuxuryModel();

  foreach (Feature f in bm.GetFeatures)
  {
    sb.AppendLine(f.Name);
  }
  MessageBox.Show(sb.ToString());
}
于 2009-06-12T23:54:39.677 回答