Переопределяющие поля или свойства в подклассах

Ну, любая конкретная причина не сделать Proxy своей собственной структурой?

В любом случае у вас есть 2 варианта:

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

type Configuration struct {
    Val string
    Proxy
}

type Proxy struct {
    Address string
    Port    string
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: Proxy{
            Address: "addr",
            Port:    "port",
        },
    }
    fmt.Println(c)
}

Менее правильный и уродливый способ, но все еще работает:

c := &Configuration{
    Val: "test",
    Proxy: struct {
        Address string
        Port    string
    }{
        Address: "addr",
        Port:    "80",
    },
}
136
задан Frans 28 November 2008 в 16:58
поделиться

6 ответов

Из этих трех решений только Опция 1 полиморфная .

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

решение предупреждения не состоит в том, чтобы добавить ключевое слово “new”, но реализовать Опцию 1.

при необходимости в поле, чтобы быть полиморфными, необходимо перенести его в Свойство.

Опция 3 в порядке don’t при необходимости в полиморфном поведении. Необходимо помнить, хотя, что, когда во времени выполнения к свойству MyInt получают доступ, производный класс не имеет никакого контроля на возвращенном значении. Базовый класс отдельно способен к возвращению этого значения.

Это - то, как действительно полиморфная реализация Вашего свойства могла бы посмотреть, позволив производным классам быть в управление .

abstract class Parent
{
    abstract public int MyInt { get; }
}

class Father : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "X" and return a value */ }
    }
}

class Mother : Parent
{
    public override int MyInt
    {
        get { /* Apply formula "Y" and return a value */ }
    }
}
132
ответ дан 23 November 2019 в 23:35
поделиться

Опция 2 является обреченным на неудачу - Вы не можете переопределение поля, Вы можете только скрываться их.

Лично, я пошел бы для опции 1 каждый раз. Я пытаюсь сохранить поля частными в любом случае. Это - то, если действительно необходимо смочь переопределить свойство вообще, конечно. Другая опция состоит в том, чтобы иметь свойство только для чтения в базовом классе, который установлен от параметра конструктора:

abstract class Mother
{
    private readonly int myInt;
    public int MyInt { get { return myInt; } }

    protected Mother(int myInt)
    {
        this.myInt = myInt;
    }
}

class Daughter : Mother
{
    public Daughter() : base(1)
    {
    }
}

Это - вероятно, самый соответствующий подход, если значение не переключает время жизни экземпляра.

18
ответ дан 23 November 2019 в 23:35
поделиться

Вы могли определить что-то вроде этого:

abstract class Father
{
    //Do you need it public?
    protected readonly int MyInt;
}

class Son : Father
{
    public Son()
    {
        MyInt = 1;
    }
}

By, устанавливающий значение как только для чтения, это гарантирует, что значение для того класса остается неизменным в течение времени жизни объекта.

я предполагаю, что следующий вопрос: почему Вам нужен он?

4
ответ дан 23 November 2019 в 23:35
поделиться

опция 2 является плохой идеей. Это приведет к чему-то названному затенением; В основном у Вас есть два различных участника "MyInt", один в родительском элементе и другом в дочернем элементе. Проблема с этим, то, что методы, которые реализованы в родительском элементе, сошлются на "MyInt" родительского элемента, в то время как методы, реализованные в дочернем элементе, сошлются на "MyInt" дочернего элемента. это может вызвать некоторые серьезные проблемы удобочитаемости и беспорядок позже по линии.

Лично, я думаю, что наилучший вариант равняется 3; потому что это обеспечивает ясное централизованное значение и может быть сослано внутренне детьми без стычки определения их собственных полей - который является проблемой с опцией 1.

7
ответ дан 23 November 2019 в 23:35
поделиться

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

abstract class Aunt
{
    protected int MyInt;
    protected Aunt(int myInt)
    {
        MyInt = myInt;
    }

}

, Конечно, у Вас затем все еще есть опция создания частного поля и затем, в зависимости от потребности, выставляя метод считывания защищенной или общественной собственности.

0
ответ дан 23 November 2019 в 23:35
поделиться

Я пошел бы с опцией 3, но имел бы краткий обзор setMyInt метод, который подклассы вынуждены реализовать. Таким образом, у Вас не будет проблемы производного класса, забывающего установить его в конструкторе.

abstract class Base 
{
 protected int myInt;
 protected abstract void setMyInt();
}

class Derived : Base 
{
 override protected void setMyInt()
 {
   myInt = 3;
 }
}

Между прочим, с опцией один, если Вы не указываете набор; в Вашем свойстве абстрактного базового класса производный класс не должен будет реализовывать его.

abstract class Father
{
    abstract public int MyInt { get; }
}

class Son : Father
{
    public override int MyInt
    {
        get { return 1; }
    }
}
0
ответ дан 23 November 2019 в 23:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: