C#中的抽象类和方法

时间:2012-01-20 19:02:04

标签: c# inheritance abstract-class

我想为我的应用程序中继承的所有参数类创建一个抽象基类。所有参数都有名称,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);
    }
}

5 个答案:

答案 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)

我可以看到您的代码有四个问题:

  1. 您正在重新定义3个共享属性,并且您尝试将它们命名为与现有字段相同。这是不允许的。最简单的方法是在继承类中实现Value的方式实现基类中的属性:使用支持字段。在C#3.0及更高版本(Visual Studio 2008及更高版本)中,您可以将自动实现的属性与私有setter一起使用。这将使编译器为您创建支持字段。例如:

    public string ParameterName { get; private set; }
  2. 您将SetProperties方法声明为abstract。这应该是virtualabstract表示子类必须定义整个实现。情况并非如此。

  3. 在您的派生类中,您覆盖SetValues但该方法名为SetProperties

  4. 您将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;
    }

}