Почему не красиво в конструкторе вызывать вирт метод
От:
Аноним
Дата:
27.07.10 06:22
Оценка:
Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются. почему такой код не красив?
Re: Почему не красиво в конструкторе вызывать вирт метод
Здравствуйте, Аноним, Вы писали:
А>Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются. почему такой код не красив?
Это потенциально опасно тем, что будет вызван метод производного класса до того как отработает конструктор производного класса, а значит инициализирует все поля.
Re: Почему не красиво в конструкторе вызывать вирт метод
Здравствуйте, Аноним, Вы писали:
А>Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются. почему такой код не красив?
При создании экземпляра подкласса будет вызван конструктор суперкласса, а то вызовет свою реализацию метода Connect, а не реализацию подкласса.
Re[2]: Почему не красиво в конструкторе вызывать вирт метод
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются. почему такой код не красив?
А>При создании экземпляра подкласса будет вызван конструктор суперкласса, а то вызовет свою реализацию метода Connect, а не реализацию подкласса.
Это справедливо для C++, но не для .NET.
Re[2]: Почему не красиво в конструкторе вызывать вирт метод
Здравствуйте, Аноним, Вы писали:
А>При создании экземпляра подкласса будет вызван конструктор суперкласса, а то вызовет свою реализацию метода Connect, а не реализацию подкласса. :)
Это в C++ вызов вирт. метода из ктора приведёт к вызову метода родительского класса. (Указатель на vtable устанавливается дважды: инициализируется указателем на таблицу базового класса, впоследствии перезаписывается указателем на таблицу производного.)
Здравствуйте, Аноним, Вы писали:
А>Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются.
Лучше передавайте стратегию подключения.
А>почему такой код не красив?
abstract class A
{
protected A(string host, int? port) {
Connect(host, port);
}
protected virtual void Connect(string host, int? port) {
}
}
class B : A
{
public B(string host, int? port, string localPath) : base(host, port) {
LocalPath = localPath ?? String.Empty;
}
public string LocalPath { get; private set; }
protected override void Connect(string host, int? port) {
InternalConnect(host, port, LocalPath); // Упс
}
}
Получается, что производный класс завязан на то, что необходимые для подключения параметры передаются в базу и не может расширить их. С другой стороны, чем вызвана необходимость ввызова Connect именно из базы?
Со стратегиями может быть как-то так или даже как-то совсем иначе:
interface IConnection
{
void Connect();
}
abstract class A
{
protected A(IConnection connection) {
if(connection == null) {
throw new ArgumentNullException("connection");
}//if
Connection = connection;
Connection.Connect();
}
protected IConnection Connection { get; private set; }
}
class B : A
{
public B(string host, int? port) : base(new BConnection(host, port)) {
}
private sealed class BConnection : IConnection
{
public BConnection(string host, int? port) {
// …
}
public void Connect() {
//…
}
}
}
class C : A
{
public B(string host, int? port, string localPath) : base(new CConnection(host, port, localPath)) {
}
private sealed class CConnection : IConnection
{
public BConnection(string host, int? port, string localPath) {
// …
}
public void Connect() {
//…
}
}
}
Help will always be given at Hogwarts to those who ask for it.
Re: Почему не красиво в конструкторе вызывать вирт метод
Здравствуйте, Аноним, Вы писали:
А>Я хочу в конструктор передать параметры и в нём же вызвать Connect который подключается к серверу. Метод Connect делаю виртуальным, т.к. способы подключения различны и в производных классах меняются. почему такой код не красив?
Как правило такой код требует от тех, кто им будет пользоваться большей осторожности и опыта, а это нельзя гарантировать для reusable компонентов.
Я использовал виртуальные методы в конструкторе лишь раз, и даже не могу вспомнить зачем Помню только, что затем отказался от них в пользу более понятного и простого кода.
Re[2]: Почему не красиво в конструкторе вызывать вирт метод