2016-09-20 48 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 

结果如预期BE " 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" 
} 

执行父功能独生子女之前先运行。如果您有多个孩子,并且您希望在调用某个函数时应用所有这些功能,我认为使用这种mixin技术是滥用行为,但这不是此技术的目的(添加功能)。

如果你想添加功能的功能,请看看修饰器设计模式。

关于trait Child3 extends Parent //<-- not override foo, and no error使用reular编码是不可能的。你可以定义宏,但我不会建议它,因为它是实验性的,这意味着它可以从scala sdk中移除。

相关问题