我想创建一个可以在属性中使用不同类型值的类。我正在尝试使用多态,但我仍然没有学习如何正确地做到这一点,因此我的建议请求。
我有一个基类和两个继承它的类:
public abstract class BaseClass
{
public string Name { get; set; }
public Unit Unit { get; set; }
}
public class DerivedClassFloat : BaseClass
{
public float Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
一切都很好,我可以创建一个List并添加不同的专用子类。当我需要更改列表中项目的值时,我的问题出现了:
foreach (var item in ListOfBaseClasses)
{
if(item is DerivedClassFloat)
((DerivedClassFloat) item).Value = float.NaN;
if (item is DerivedClassString)
((DerivedClassString) item).Value = string.Empty;
}
根据我所读到的,这看起来像代码味道。是否有更好的方法来根据我尝试分配的类型访问派生类的value属性?
当你想根据值创建正确的子类时呢?
BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
newClass = new DerivedClassString(){Value = "Hello"};
我读过有关覆盖虚拟方法的内容,但如果我想处理该值,而不是添加或更改它,那么这种方法是有效的...也许我错过了什么?
我应该更加具体,道歉,我不习惯在这个伟大的网站上发帖提问。
我需要一个由属性列表组成的属性。每个属性都有一个名称和一个值,但值可以是不同的类型。例如:
public class Organism
{
public string Name { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public string AttributeName { get; set; }
public object AttributeValue { get; set; }
}
对于给定的生物,我可以有几个属性持有不同的值类型。我想避免使用对象类型,这样我就不必转换为正确的类型。我虽然属性多态性是优雅地处理这种情况的解决方案,但后来我发现自己使用了If ..然后,这与首先没有什么不同。
答案 0 :(得分:2)
如果在您的特定情况下要重置Value
,则可以在基类中定义抽象ResetValue
方法,该方法将由派生类实现。
至于你的第二个案例,你应该看看Creational Design Patterns,特别是工厂和原型设计模式。
答案 1 :(得分:2)
您可以将Generics用于此特定情况:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
}
public class DerivedClassFloat : BaseClass<float>
{
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass<string>
{
public override string ToString()
{
return Value;
}
}
答案 2 :(得分:1)
您可以使用泛型来定义类型,实现子类将Value
类型设置为类型约束:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedFloat : BaseClass<float> {}
public class DerivedString : BaseClass<string> {}
答案 3 :(得分:1)
多态行为适用于抽象。根据您的尝试,您可以减少代码气味,将代码中的可变性移动到基础classess。
我建议使用如下的属性写入方法而不是。你可以这样做。
public void setValue(string val, Type type);//move this to your base class
Class MyValue{
private string strVal;
private int intVal;
//constructor
MyValue(string val, Type type){
//check the type enum here and set the values accordingly
}
}
then when set values
foreach (var item in ListOfBaseClasses)
{
item.setValue = MyValue("",Type.INT);
}
答案 4 :(得分:0)
我不太确定你用这种方法想要实现什么 - Value属性的类型不同,基类上也没有Value属性,这表明从基类派生的其他类型可能根本没有。
如果你的所有类都需要一个Value属性,那么也许它应该是最通用的类型object
- 你可以将它放在基类上,但这需要在派生类中转换值。
但是,您可以使用NullObject
来表示缺少值,您可以为每个派生类赋予Value属性。
答案 5 :(得分:0)
您可以使用abstract factory pattern。考虑这个例子:
// Base class
class Button
{
protected Button()
{
}
public string Name { get; set; }
}
// Factory interface
public interface ButtonFactory
{
Button CreateButton();
}
// And the concrete classes
class WindowsButton : Button
{
// ...
}
class WindowsButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new WindowsButton();
}
}
class MacButton : Button
{
// ...
}
class MacButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new MacButton();
}
}
此外,您可以将abstract factory pattern与strategy pattern结合使用,以封装随类型更改的自定义行为。