Абстрактные классы и методы в C # - PullRequest
0 голосов
/ 20 января 2012

Я хочу создать абстрактный базовый класс для всех классов типа Paramter, чтобы наследовать в моем приложении.Все параметры будут иметь имя, ID и обязательные свойства.

Все параметры будут иметь свои свойства, установленные из XML с помощью метода SetProperties (класс 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 ]

4 голосов
/ 20 января 2012

Я бы сделал просто, вот так:

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
    }
}

Управлять таким способом проще и понятнее.Переместить общие свойства в отдельный базовый класс - это хорошо, но управление постоянством (Save / Load) оставьте для детей. Они должны знать, как это сделать.

Предоставленный код имеет пару проблем:

  • abstract метод не может иметь тело

  • у вас странный public override void SetValues(string xml), который, я думаю, должен быть
    public override void SetProperties(string xml)

1 голос
/ 20 января 2012

Есть четыре проблемы с вашим кодом, которые я вижу:

  1. Вы переопределяете 3 общих свойства и пытаетесь назвать их так же, как существующее поле.Это не разрешеноСамый простой способ - реализовать свойства в базовом классе так же, как вы реализовали Value в наследующем классе: с полями поддержки.В C # 3.0 и выше (Visual Studio 2008 и выше) вы можете использовать автоматически реализуемые свойства с частным установщиком.Это заставит компилятор создавать резервные поля для вас.Например:

    public string ParameterName { get; private set; }
  2. Вы объявляете метод SetProperties как abstract.Это должно быть virtual.abstract означает, что подкласс должен определять всю реализацию.Это не тот случай.

  3. В вашем производном классе вы переопределяете SetValues, но метод называется SetProperties.

  4. Выобъявляют Parameter1 абстрактным.Вы не можете создавать экземпляры абстрактных классов, поэтому вам также придется наследовать класс от Parameter1, чтобы использовать его.Я предполагаю, что вы просто захотите удалить квалификатор abstract.

0 голосов
/ 20 января 2012

Как уже отмечалось, не переусердствуйте.Я бы объявил абстрактный класс параметров так, чтобы он имел единственный конструктор (защищенный), который принимает обязательные три свойства (Name, IsRequired и ID).Это означает, что каждый конкретный подтип должен правильно его построить.

Тогда у меня будет абстрактный фабричный метод , CreateInstance(), который должен реализовывать каждый конкретный подтип, возвращая экземпляр AbstractParameter.Зачем?Читайте о принципе замены Лискова .В реальном мире, конечно, может иметь больше смысла, чем использовать фабричный метод , чтобы отделить заботу о том, как создавать экземпляры параметра, от заботы о том, что является параметромПереместив логику построения в собственный фабричный класс (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;
    }

}
0 голосов
/ 20 января 2012

Я бы сделал общие свойства Базового класса общедоступными с защищенными установщиками, после чего вы можете получить к ним доступ из любых производных классов, без использования дублирующего кода!

protected string ParameterName { get; protected set; }; 
protected bool IsRequired  { get; protected set; }; 
protected int ParameterId  { get; protected set; };
0 голосов
/ 20 января 2012

Вы делаете это слишком сложным.Первые три свойства могут быть унаследованы от базового класса:

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

Youдолжен сделать его виртуальным, если вы хотите дать ему базовую реализацию.

(И вы должны переопределить SetProperties, а не SetValue.)

...