2015-06-05 2 views
-4

Что касается следующей модели, как я могу написать метод Make для выполнения цели использования ?Создайте экземпляр производного класса с использованием статического метода базового класса

Примечание: Я не хочу повторять метод Make в каждом производном классе.

Использование:

Derived instance = Drived.Make(); 
AnotherDerived instance = AnotherDrived.Make(); 
ThirdDerived instance = ThirdDrived.Make(); 

Модель:

class Base 
{ 
    public static Base Make() 
    { 
     // What to write here? 
    } 
} 

class Derived : Base 
{ 
} 

class AnotherDerived : Base 
{ 
} 

class ThirdDerived : Base 
{ 
} 
+3

??? = 'return new Derived();'. Пожалуйста, уточните свой вопрос. Каковы ваши намерения? – usr

+0

@usr Прошу вас, пожалуйста, дополнить вопрос до голосования? – Hans

+1

Возможно, перед отправкой вопроса, вы должны его заполнить (хотя я не сделал нисходящего). –

ответ

3

Вы бы написать:

class Derived : Base 
{ 
    public static Derived Make() 
    { 
     ??? 
    } 
} 

Это не имеет значения, что база имеет метод Make, они оба они статические, поэтому не имеют никакого отношения друг к другу.

+0

Я не хочу повторять Make в каждом производном классе – Hans

+0

@ Почему вам нужно сделать? Используйте 'new'. – usr

+0

статические классы не наследуются, поэтому вам придется повторять их в каждом классе. Вы просто пытаетесь построить завод? http://en.wikipedia.org/wiki/Factory_method_pattern. – shf301

0

Вы можете определить конструкторы преобразования для каждого производного класса и использовать make следующим образом: (Derived) Derived.Make();

+0

Повторение Make в каждом производном классе не является опцией – Hans

+0

Make будет только в базовом классе, вы определяете конструкторы преобразования только в каждом производном классе. – Alioza

1

Чтобы иметь только один метод, вы можете использовать общий метод:

class Base 
{ 
    public static T Make<T>() where T : Base 
    { 
     if (typeof(T) == typeof(Derived)) 
     { 
      return (T)(object)new Derived(); 
     } 
     // obviously more cases in here. just for illustration. 
     else 
     { 
      return null; 
     } 
    } 
} 

, то вы должны были бы назвать его как

Derived d = Base.Make<Derived>(); 

Там нет возможности написать один метод в базе класса и имеют Derived.Make и AnotherDerived.Make что-то еще (кроме того, возвращают разные типы, как ваш пример), если вы не рассматриваете возможность генерации кода. Это не разные методы под капотом. Они действуют как псевдонимы до Base.Make, если вы не определяете новый метод в каждом производном классе.

+2

Если я смотрю на кодовую базу и вижу «Base.Make », я бы хотел быть O_o. –

+0

@YuvalItzchakov Не мой любимый образец, но тем более, что я считаю это злоупотреблением дженериками. 'Make ' не может действительно сделать какой-либо тип T. Он может только сделать несколько типов, которые я жестко закодировал, которые затем должны быть задокументированы. Если он может ограничить, кто наследует от Base, то почему бы мне просто не поместить метод в каждый производный класс, поскольку они находятся под моим контролем. –

+0

@ mike.z Я с тобой. Намерение сделать такой метод «Make» до сих пор неясно мне из вопроса OP. Чего он на самом деле пытается достичь. –

2

Несмотря на все хорошие решения, которые дали люди, я пришел к такому выводу, что это невозможно. Источником моего вопроса является непонимание того, как статические методы работают над производными классами. Я только узнал, что Derived.Make() сразу же скомпилирован в Base.Make(), следовательно Base никогда не знает, на какой тип Make был вызван. Derived.Make() - это просто ярлык.

+1

Там вы идете. Рад, что ваша проблема решена (вроде). Все существующие ответы предполагают ответы, которые теперь устарели. Вот почему я спрашиваю подробности * перед ответом. Надеюсь, ты получишь, откуда я. – usr

+0

Вы абсолютно правы. Существует один трюк, который вы можете сделать, если у вас все в порядке, когда «Base» является родовым типом ([«любопытно повторяющийся» шаблон] (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)). См. Ответ bcwhims. –

2

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

class Base<T> where T : new() 
{ 
    public static T Make() 
    { 
     return new T(); 
    } 
} 

class Derived : Base<Derived> 
{ 
} 

class AnotherDerived : Base<AnotherDerived> 
{ 
} 

class ThirdDerived : Base<ThirdDerived> 
{ 
} 
+0

Я тоже думал об этом решении. С помощью этого решения 'var instance = ThirdDerived.Make();' будет строго типизированным экземпляром ThirdDerived. Это происходит не потому, что метод 'static'« модифицирован »в производном классе. Синтаксис 'ThirdDerived.Make()' рассматривается компилятором как 'Base .Make()' (потому что базовый класс 'ThirdDerived' является' Base '). –

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