我写这个例子来帮助解释。如您所见,我有一个对象层次结构。我想修改GetFeatures()函数,只返回实例化对象类型I的构造函数添加的功能。例如,BasicModel.GetFeatures(new LuxuryModel())应仅返回“皮座”和“天窗”功能。如果必须,我不介意使用反射。
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
答案 0 :(得分:1)
如果要保留当前的层次结构/属性,只需创建基类的实例,然后从派生类中的要素中减去基类中的要素。
或者,您可能需要考虑稍微更改类层次结构,以使自己更容易。
例如,您可以将Features属性拆分为两个属性,比如ModelFeatures和AllFeatures。
ModelFeatures特定于当前模型(“Leather Seodes”和“Sunroof”for LuxuryModel等).AllFeatures返回MyBase.AllFeatures和ModelFeatures的并集。这使得获取当前Model的功能成为一种简单的属性访问。
P.S。请原谅我的VB错误,C#是我首选的语言。
答案 1 :(得分:1)
我对VB.NET语法并不熟悉,所以这里应该有C#语法:
public IList<Function> GetFeatures(BasicModel model)
{
return model.Features.Where(f => f.Model.GetType() == model.GetType()).ToList();
}
答案 2 :(得分:1)
(基于您的上述示例代码)
老实说,我不认为这属于你的Car Heirachy,在我看来,你想要获取静态数据并使用你的基类作为它的容器,并将你的后代类型作为关键。正如您所看到的,这会导致一些简单的笨拙或过于复杂的编码。
我更倾向于将静态数据放在它所属的位置(在本例中)与Feature类本身。我不是一个VB人,所以这个代码片段在C#中。
因此,在Feature类本身中,有一个 static 属性(或方法)
public static IEnumerable<Feature> GetLuxuryFeatureSets
{
get
{
yield return new Feature() { Name = "Leather Seats" };
yield return new Feature() { Name = "Sunroof" };
}
}
并重复其他型号。所以现在你有了一个容器,你的静态数据是有意义的,类本身。
答案 3 :(得分: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();
}
答案 4 :(得分:1)
如果你不希望这些数据是静态的另一种方法(参见我的另一个答案),你可以将它扩展到新类,并让那些类来控制功能集。然后使用多态(再次使用C#,因为我不是VB人)
在你的基类中创建一个返回特征的虚方法,在你的decenent类中覆盖属性,polymorphism允许你的变量作为类型basicmodel,只要它们被构造为后代类型就可以返回正确的列表。
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());
}