C#中的抽象类和方法

本文关键字:方法 抽象类 | 更新日期: 2023-09-27 18:20:59

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

C#中的抽象类和方法

我会简单地这样做:

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的方法相同:使用backing字段。在C#3.0及以上版本(Visual Studio 2008及更高版本)中,您可以将自动实现的属性与专用setter一起使用。这将使编译器为您创建支持字段。例如:

    公共字符串ParameterName{get;private set;}
  2. 您正在将SetProperties方法声明为abstract。这应该是virtualabstract意味着子类必须定义整个实现。这里的情况并非如此。

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

  4. 您正在将Parameter1声明为抽象。你不能实例化抽象类,所以你必须从Parameter1继承一个类才能使用它。我猜你只想删除abstract限定符。

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

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

你把它搞得太复杂了。前三个属性可以从基类中继承:

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

如前所述,不要想太多。我会声明抽象参数类,这样它就有一个单独的构造函数(受保护),它接受三个强制性属性(Name、IsRequired和ID)。这意味着每个混凝土子类型都必须正确构造它。

然后,我会有一个抽象的工厂方法CreateInstance(),每个具体的子类型都必须实现,返回AbstractParameter的一个实例。为什么?阅读利斯科夫替代原则。当然,在现实世界中,通过将构造逻辑移动到其自己的工厂类AbstractParameterFactory?)中,将如何创建参数实例的问题与作为参数的问题分离开来,而不是使用出厂方法,可能会更有意义。

不过,我可能会注意到,您缺少一个所有参数都具有的基本属性:Value。您可以考虑将抽象参数的基类设为泛型。

总之,这是我的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;
    }
}