Как изменить значения постоянных или статических переменных при наследовании класса?

У меня есть вопрос, похожий на этот: Могу ли я иметь базовый класс, в котором каждый производный класс имеет собственную копию статического свойства?, но ответ не показался мне очень убедительным.

По сути, у меня есть класс со свойством константы, и я хочу создать класс, который имеет все те же методы, но использует другое значение для переменной. Для простой аналогии представьте, что у меня есть класс, который частично выглядит так:

public class Triangle
{
    public const NumSides = 3;
    int sideLength;

    public int Perimeter()
    {
        return NumSides * sideLength;
    }
}

и теперь я хотел создать класс Square, который был бы точно таким же, как класс Triangle, за исключением того, что NumSides теперь было 4.

Другими словами, мне нужен класс, который теперь полностью выглядит примерно так:

public class Square : Triangle
{
    public const NumSides = 4;
}

но он по-прежнему имеет доступ ко всем методам класса Triangle. (Я могу справиться с написанием нового конструктора, если это необходимо, но я не хочу копировать более дюжины или около того методов из исходного класса. Все они должны вести себя точно так же, но теперь NumSides имеет значение из 4.)

Я не могу понять, как это сделать, либо с NumSides, являющимся константой, либо со статическим свойством только с функцией получения. Если я попытаюсь переопределить константу, я получу «Модификатор «переопределение» недействителен для этого элемента». Когда я пытаюсь переопределить версию статического свойства, я получаю сообщение, эквивалентное «Статический элемент Triangle.NumSides не может быть помечен как переопределяемый, виртуальный или абстрактный».

И да, я пытался создать класс Shape, поместив в него всю функциональность, а затем наследовать от этого класса и Triangle, и Square. Однако я столкнулся с той же проблемой с NumSides. Как я могу изменить действующее значение константы или статической переменной/свойства при создании нового класса?


person Galendo    schedule 15.07.2014    source источник
comment
Квадрат является разновидностью треугольника? Кажется, моя голова просто немного взорвалась.   -  person Daniel Mann    schedule 15.07.2014


Ответы (2)


И да, я пытался создать класс Shape, поместив в него всю функциональность, а затем наследовать от этого класса и Triangle, и Square.

Это правильный подход. Square не является Triangle и не должен быть его подклассом.

Однако я столкнулся с той же проблемой с NumSides. Как я могу изменить действующее значение константы или статической переменной/свойства при создании нового класса?

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

public abstract class Shape
{
   public abstract int NumSides { get; }
   // Other functionality...
}

Переопределить через:

public override int NumSides { get { return 3; } } // For triangle
person Reed Copsey    schedule 15.07.2014
comment
Это хорошо, спасибо. Единственная проблема заключается в том, что это полностью портит большинство моих статических методов, поскольку теперь я больше не могу ссылаться на константу в этих методах. Это немного выходит за рамки вопроса, который я задал, но это значительный побочный эффект этого решения, о котором стоит упомянуть. - person Galendo; 15.07.2014

Чтобы переопределить член, он должен быть виртуальным, а константа или статика не могут быть виртуальными. Вместо этого сделайте его свойством:

public class Triangle
{
    public virtual int NumSides { get { return 3; } }

    int sideLength;

    public int Perimeter()
    {
        return NumSides * sideLength;
    }
}

public class Square : Triangle
{
    public override int NumSides { get { return 4; } }
}

Тот же подход будет работать для класса Shape, но вы можете сделать его абстрактным и встроить в виртуальный, чтобы избежать реализации свойства в классе Shape.

person Guffa    schedule 15.07.2014