Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Коснструктор при наследовании абстрактного класса

842
25 ноября 2009 года
sigmov
301 / / 16.09.2008
Для начала упрощенный код:
Код:
public abstract class Class<This>   //Объявляем абстрактный класс Class<This>
    where This: Class<This>         //Объявляем, что тип This является производным от Class<This>
{
    public Class(int x)             //Объявляем поддержку конструктора с параметром int
    {
    }
    public This Create(int x)       //Задаем метод возвращающит тип This
    {
        return new This(x);         //Создаем тип This // Ошибка(!)
    }
}


И вот что непонятно: Почему строка return new This() вызывает ошибку? Ведь This является производным от Class<This> и должен поддерживать данный конструктор....

Если кто знает причину или как этого избежать - буду очень благодарен!
5
25 ноября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
Почему строка return new This() вызывает ошибку? Ведь This является производным от Class<This> и должен поддерживать данный конструктор....


Он может не поддерживать этот конструктор. Контр пример:

 
Код:
public class Base {
   public Base(int x) { }
}

public class Derived : Base {
   public Derived(string a, int x) : base(x) { }
}
Если все-таки нужно создавать экземпляр объекта, то нужно выполнять это посредством Activator.CreateInstanсe:
 
Код:
This t = (This) Activator.CreateInstance(typeof(This), x);
842
25 ноября 2009 года
sigmov
301 / / 16.09.2008
Цитата: hardcase
 
Код:
This t = (This) Activator.CreateInstance(typeof(This), x);


Предложение хорошее. Но в силу приведенного вами же контрпримера оно теряет смысл :(
Да и скорость является критичным параметром.
Пришлось оставить реализацию "потомкам"

Код:
public abstract class Class<This>           //Объявляем абстрактный класс Class<This>
     where This : Class<This>                    //Объявляем, что тип This является производным от Class<This>
     {
         protected abstract This CreateThis(int x);
         public Class(int x)                    //Объявляем поддержку конструктора с параметром int
         {
         }
         public This Create(int x)              //Задаем метод возвращающит тип This
         {
             return this.CreateThis(x);        //Создаем тип This // Ошибка(!)
         }
     }
5
25 ноября 2009 года
hardcase
4.5K / / 09.08.2005
Цитата: sigmov
Предложение хорошее. Но в силу приведенного вами же контрпримера оно теряет смысл :(


В .NET, к сожалению, нельзя накладывать обобщенные ограничения на конструкторы, я уже как-то отмечал этот факт на форуме (искать тему лениво). Но, все же, если семейство T-типов достаточно однородно, можно применить паттерн отложенной инициализации:

Код:
public interface IInitializable {
    void Initialize(int x);
}

public class Container<T> where T : IInitializable, new() {
    public T MakeInstance(int x) {
        T obj = new T();
        obj.Initialize(x);
        return obj;
    }
}
Такой интерфейс IInitializable называется контрактом взаимодействия.
341
30 ноября 2009 года
Der Meister
874 / / 21.12.2007
Можно параметризовывать конструктор порождающим делегатом:
Код:
public abstract class Base<This>
where This : Base<This>
{
    public delegate This ObjectCreator();

    readonly ObjectCreator _creator;

    protected Base(ObjectCreator object_creator)
    {
        _creator = object_creator;
    }

    public This Create()
    {
        return _creator();
    }
}

class Derrived : Base<Derrived>
{
    public Derrived(int x)
        : base(() => new Derrived(x))
    {
        X = x;
    }

    public int X { get; private set; }
}

class Program
{
    static void Main(string[] args)
    {
        var derrived = (new Derrived(123)).Create();
    }
}
Либо ввести фабричный метод:
Код:
public abstract class Base<This>
where This : Base<This>
{
    protected Base(int x)
    {
        X = x;
    }

    public int X { get; private set; }

    public abstract This Create();
}
 
class Derrived : Base<Derrived>
{
    public Derrived(int x, int y)
        : base(x)
    {
        Y = y;
    }
    public int Y { get; private set; }

    public override Derrived Create()
    {
        return new Derrived(X, Y);
    }
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог