我想为我的应用程序中继承的所有参数类创建一个抽象基类。所有参数都有名称,ID和所需属性。
所有参数都将通过SetProperties方法从XML设置其属性(下面显示的XmlParser类仅用于演示)。
由于所有参数都具有相同的3个属性,我希望基类设置这些属性,但让继承类扩展SetProperties方法以设置它包含的其他属性。
我在考虑在Control
上覆盖事件。
以下是我正在思考的一个示例,尽管它不起作用。
abstract class ParameterBase
{
protected string ParameterName;
protected bool IsRequired;
protected int ParameterId;
public abstract void SetProperties(string xml)
{
this.ParameterName = XmlParser.GetParameterName(xml);
this.IsRequired = XmlParser.GetIsRequired(xml);
this.ParameterId = XmlParser.GetParameterId(xml);
}
}
abstract class Parameter1 : ParameterBase
{
private string _value;
public string ParameterName
{
get { return base.ParameterName; }
}
public bool IsRequired
{
get { return base.IsRequired; }
}
public int ParameterId
{
get { return base.ParameterId; }
}
public string Value
{
get { return _value; }
}
public Parameter1()
{
}
public override void SetProperties(string xml)
{
base.SetProperties(xml);
_value = XmlParser.GetValue(xml);
}
}
答案 0 :(得分:4)
我会这样做,就像这样:
abstract class ParameterBase
{
protected string ParameterName;
protected bool IsRequired;
protected int ParameterId;
public abstract void SetProperties(string xml);
}
并衍生出一个:
public class Parameter1 : ParameterBase
{
public override void SetProperties(string sml)
{
//set properties including those ones of parent
}
}
以这种方式管理更容易,更清晰。将公共属性移动到单独的基类中它是好的,但是持久性管理(保存/加载),留给孩子。 他们应该知道如何做到这一点。
提供的代码有几个问题:
abstract
方法不能有身体
你有奇怪的public override void SetValues(string xml)
,我认为应该是
public override void SetProperties(string xml)
答案 1 :(得分:1)
我可以看到您的代码有四个问题:
您正在重新定义3个共享属性,并且您尝试将它们命名为与现有字段相同。这是不允许的。最简单的方法是在继承类中实现Value
的方式实现基类中的属性:使用支持字段。在C#3.0及更高版本(Visual Studio 2008及更高版本)中,您可以将自动实现的属性与私有setter一起使用。这将使编译器为您创建支持字段。例如:
public string ParameterName { get; private set; }
您将SetProperties
方法声明为abstract
。这应该是virtual
。 abstract
表示子类必须定义整个实现。情况并非如此。
在您的派生类中,您覆盖SetValues
但该方法名为SetProperties
。
您将Parameter1
声明为抽象。您无法实例化抽象类,因此您必须从Parameter1
继承一个类才能使用它。我猜您只想删除abstract
限定符。
答案 2 :(得分:0)
你太复杂了。前三个属性可以从基类中获取:
public abstract class ParameterBase
{
public string ParameterName { get; private set; }
public bool IsRequired { get; private set; }
public int ParameterId { get; private set; }
public virtual void SetProperties(string xml)
{
ParameterName = XmlParser.GetParameterName(xml);
IsRequired = XmlParser.GetIsRequired(xml);
ParameterId = XmlParser.GetParameterId(xml);
}
}
public class Parameter1 : ParameterBase
{
public string Value { get; private set; }
public override void SetProperties(string xml)
{
base.SetProperties(xml);
Value = XmlParser.GetValue(xml);
}
}
另请注意,抽象方法不能有正文,而是以分号结尾:
public abstract void SetProperties(string xml);
如果要为其提供基本实现,则必须将其分解为虚拟。
(您必须覆盖SetProperties
,而不是SetValue
。)
答案 3 :(得分:0)
我会使用受保护的setter使公共Base类属性为Public,然后您可以从任何派生类访问它们,不使用重复代码!
protected string ParameterName { get; protected set; };
protected bool IsRequired { get; protected set; };
protected int ParameterId { get; protected set; };
答案 4 :(得分:0)
如上所述,不要过度思考。我将声明抽象参数类,以便它具有一个构造函数(protected),它具有强制性的三个属性(Name,IsRequired和ID)。这意味着每个具体的子类型必须正确构建它。
然后,我有一个抽象的工厂方法,CreateInstance()
,每个具体的子类型必须实现,返回AbstractParameter的一个实例。为什么?阅读Liskov Substitution Principle。当然,在现实世界中,可能更有意义的是,而不是使用工厂方法,将如何从 的关注点创建参数实例的问题分开一个参数,将构造逻辑移动到自己的工厂类(AbstractParameterFactory
?)。
无论如何,这是我的AbstractParameter
课程:
public abstract class AbstractParameter
{
public string Name { get ; protected set ; }
public bool IsRequired { get ; protected set ; }
public int ID { get ; protected set ; }
protected AbstractParameter( string name , bool isRequired , int id )
{
this.Name = name;
this.IsRequired = isRequired;
this.ID = id;
this.Value = default(T) ;
return;
}
public abstract AbstractParameter CreateInstance( string xml ) ;
}
从AbstractParameter
派生的具体参数类可能看起来像这样:
public class ConcreteParameter : AbstractParameter
{
public ConcreteParameter( string name , bool isRequired , int id ) : base( name , isRequired , id )
{
return ;
}
public override AbstractParameter CreateInstance( string xml )
{
string name = XmlParser.GetName();
bool required = XmlParser.GetIsRequired();
int id = XmlParser.GetID();
ConcreteParameter instance = new ConcreteParameter( name , required , id );
return instance;
}
}