2009-04-15 2 views
7

У меня есть несколько типов, которые основаны на упрощенном Base, как показано ниже.Перегрузка «базового» конструктора или «этого» конструктора?

Я не уверен, использовать конструктор базового класса или конструктор this при перегрузке конструкторов.

ConcreteA перегружает Конструкторы чисто с помощью base конструкторов, в то время как
ConcreteB перегрузок с использованием this в течение первых двух перегрузок.

Что было бы лучшим способом перегрузки конструкторов?

public abstract class Base 
{ 
    public string Name { get; set; } 
    public int? Age { get; set; } 

    protected Base() : this(string.Empty) {} 
    protected Base(string name) : this(name, null) {} 
    protected Base(string name, int? age) 
    { 
     Name = name; 
     Age = age; 
    } 
} 

public class ConcreteA : Base 
{ 
    public ConcreteA(){} 
    public ConcreteA(string name) : base(name) {} 
    public ConcreteA(string name, int? age) : base(name, age) 
    { 
    } 
} 

public class ConcreteB : Base 
{ 
    public ConcreteB() : this(string.Empty, null){} 
    public ConcreteB(string name): this(name, null){} 
    public ConcreteB(string name, int? age) : base(name, age) 
    { 
    } 
} 

[Редактировать] Похоже, что Ян Куигли предложил в своем answer казалось, имело смысл. Если бы мне нужно было вызвать инициализацию валидаторов, ConcreteA(string) никогда не будет инициализировать валидаторы в следующем случае.

public class ConcreteA : Base 
{ 
    public ConcreteA(){} 
    public ConcreteA(string name) : base(name) {} 
    public ConcreteA(string name, int? age) : base(name, age) 
    { 
     InitializeValidators(); 
    } 
    private void InitializeValidators() {} 
} 

ответ

5

. Потому что, если вы когда-либо размещаете код в ConcreteB (string, int?), Вы хотите, чтобы конструктор string только вызывал его.

+0

Это, похоже, имеет смысл, если я буду иметь другие инициализации в конкретных конструкторах. – Sung

+0

Да, и «это» всегда будет называться «база» в конце дня. Поэтому, даже если «это» ничего не делает, оно упадет до «базы», –

1

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

2

В общем, я бы назвал это «скорее», а не «базой». Вероятно, вы снова будете использовать больше кода, если позже вы расширите свои классы.

0

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

Однако, в зависимости от класса, который вы переопределите, это может быть невозможно или добавить ненужную сложность. Это справедливо для специальных шаблонов конструктора, например, при реализации ISerializable.

2

Прекрасно смешивать и сопоставлять; в конечном счете, когда вы используете конструктор this(...), он будет в конечном итоге добраться до ctor, который сначала называет base(...). Имеет смысл повторно использовать логику там, где это необходимо.

Вы можете организовать его так, чтобы все конструкторы назывались общим (возможно, частным) конструктором this(...), который является единственным, который вызывает до base(...) - но это зависит от того, полезно ли это: и b : есть ли один base(...) ctor, который позволил бы вам.

0

Снова спросите себя, почему вы перегружаете конструктор в базовом классе? Это один достаточно:

protected Base() 

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

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

Смежные вопросы