2014-03-02 2 views
2

Итак, я пытаюсь вставить компонентную систему для игровых объектов в свои рамки, и я надеялся сохранить все компоненты в одном массиве (или map ... et.), поэтому все они могут быть легко обновлены, а классы не должны использовать предопределенные слоты для компонентов, поэтому я сделал базовый компонентный класс и создал карту компонента типа, а затем имел другие компоненты, которые расширяют базу компонент, который отлично работает, если все, что я хочу сделать, это вызвать метод обновления для всех из них, но я хочу, чтобы все они могли иметь любые методы, которые они хотят. Конечно, это не сработает, потому что компилятор не знает, какой класс может быть для каждого компонента. Затем я обнаружил, что могу применить компонент к своему типу, используя что-то вроде этого (если я знаю его тип): return cast(components.get("transform"), TransformComponent); , а затем получить доступ к функциям childs. Это хороший способ сделать что-то, или это ужасное дизайнерское решение, и я должен переработать всю структуру компонентов? жаль, если это очень неопытный вопрос, и спасибо, Николитье родительских классов в дочерние классы

(обратите внимание, я использую Haxe, но я считаю, что это относится ко всем языкам OOP)

ответ

2

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

С Haxe, вы можете использовать параметры типа как так:

var c:Map<String,BaseComponent>; 

public function getComponent<T:BaseComponent>(name:String, type:Class<T>):T { 
    if (components.exists(name)) { 
     var c = components[name]; 
     if (Std.is(c, type)) { 
      return cast c; 
     } 
    } 
    return null; // the component with that name didn't exist, or was the wrong type 
} 

Таким образом, ваше использование может быть:

var transform = componentManager.getComponent("transform", TransformComponent); 
if (transform!=null) { 
    transform.doSomething(); 
} 

В этом случае преобразование будет полностью набраны как «TransformComponent» и компилятор позволит вам получить доступ ко всем его методам и т. д.

В заключение, если у вас только один экземпляр каждого типа компонентов, вы можете сделать это еще проще:

public function addComponent<T:BaseComponent>(component:T) { 
    var type = Type.getClass(component); 
    var name = Type.getClassName(type); 
    components[name] = component; 
} 

public function getComponent<T:BaseComponent>(type:Class<T>):T { 
    var name = Type.getClassName(type); 
    return cast components[name]; // Either the component with the correct type name, or null. 
} 

componentManager.addComponent(new TransformComponent()); 
var t = componentManager.get(TransformComponent); 
$type(t); // TransformComponent, it is correctly typed 
+0

Потрясающие :) Вот именно то, что я хотел бы знать, и дженерики делает его гораздо чище ... спасибо – Nico

+0

Я думаю, что я посажу обоих этих методов в легкий доступ – Nico

+0

Только так я понимаю это полностью, как работает бросок без второго параметра или указанного типа, например, я мог бы понять: var i: Int = cast myfloat, но как он работает без указания типа? – Nico

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