繁体   English   中英

C#中的抽象类和方法

[英]Abstract classes and methods in C#

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

我会简单地这样做:

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. 您正在重新定义3个共享属性,并试图将它们命名为与现有字段相同。 这是不允许的。 最简单的方法是,以与在继承类中实现Value方式相同的方式在基类中实现属性:带后备字段。 在C#3.0及更高版本(Visual Studio 2008及更高版本)中,可以将自动实现的属性与私有设置程序一起使用。 这将使编译器为您创建后备字段。 例如:

      公共字符串ParameterName {get;  私人套装;  } 
  2. 您将SetProperties方法声明为abstract 这应该是virtual abstract意味着子类必须定义整个实现。 这里不是这样。

  3. 在派生类中,您重写SetValues但该方法称为SetProperties

  4. 您将Parameter1声明为抽象。 您无法实例化抽象类,因此也必须从Parameter1继承一个类才能使用它。 我猜您只是想删除abstract限定词。

您使它变得太复杂了。 可以从基类继承前三个属性:

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 。)

我将公共的基类属性与受保护的setter公开,然后可以从任何派生类访问它们,而无需使用重复代码!

protected string ParameterName { get; protected set; }; 
protected bool IsRequired  { get; protected set; }; 
protected int ParameterId  { get; protected set; };

如前所述,不要过度思考。 我将声明抽象参数类,以便它具有一个带有必需的三个属性(Name,IsRequired和ID)的构造函数(受保护)。 这意味着每个具体的子类型都必须正确地构造它。

然后,我有一个抽象工厂方法 CreateInstance() ,每个具体的子类型都必须实现该方法,并返回AbstractParameter的一个实例。 为什么? 阅读有关Liskov替代原理的信息 当然,在现实世界中,通过将构造逻辑移入其自己的工厂类 (而不是使用工厂方法 )将如何创建参数实例的关注与作为参数的关注分开,可能更有意义。 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;
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM