2016-09-20 7 views
1

Я не уверен, что это возможно, или я задаю неправильный вопрос здесь. Скажем, если у меня есть что-то вродеМогу ли я переместить стеклизованную логику признаков в родительскую?

trait Parent { 
    def foo : String = " Parent " 
} 

trait Child1 extends Parent { 
    override def foo : String = super.foo + " Child 1 " 
} 

trait Child2 extends Parent { 
    override def foo : String = super.foo + " Child 2 " 
} 

и использовать его как

class ChildGroup extends Child1 with Child2 
(new ChildGroup).foo 

результат, как ожидается, Ве " Parent Child 1 Child 2 "

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

trait Child3 extends Parent //<-- not override foo, and no error 

trait Child4 extends Parent { 
    override def foo : String = " Child 4 " //<-- forget super.foo + 
} 

и использовать как

class ChildGroup extends Child1 with Child2 with Child3 with Child4 
(new ChildGroup).foo 

результат будет просто " Child 4 ", и я не хочу, чтобы это произошло, я просто хочу, чтобы всегда быть стек

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

Можно ли это сделать? или есть другой вариант, который заставит других людей всегда делать super.foo + x

+0

Возможно, вы можете заставить вызов 'super' использовать макросы или плагин компилятора, но, как правило, это не очень хорошая идея. Даже если вы вызываете вызов 'super.foo', нет гарантии, что он будет использоваться правильно. Он называется _semantic binding_, и его следует избегать, поскольку он требует, чтобы клиентский код знал семантику реализуемого кода - что неудивительно, что это приводит к ошибкам. Возможно, есть разумный способ инкапсулировать то, что вы хотите в «Parent», но он может быть очень уродливым, чем первый. –

+0

Согласитесь, я не хочу макроса или плагина. Просто надеясь, что у кого-то будет приемлемое уродливое решение – izht

ответ

1

Это объектно-ориентированный вопрос.

вы можете определить родителя как:

trait Parent{ 
    public final def f():String= { 
       "Parent" +g(); 
    } 
    protected abstract def g():String 
} 

trait Child extends Parent{ 
    def g()= "Child" 
} 

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

Если вы хотите добавить функциональность к функции, пожалуйста, посмотрите на декоратор шаблон проектирования.

Отношения trait Child3 extends Parent //<-- not override foo, and no error невозможно использовать reule кодировка. вы можете определить макрос, но я бы не предложил его, потому что он экспериментальный, что означает, что он может быть удален из scala sdk.