繁体   English   中英

如何确定使用特征'''或类来“注入”?

[英]How to determine to use trait to 'with' or class to 'inject'?

在编写scala代码时,我很困惑地选择一个traitclass

起初,我有一个控制器, with几个特点:

class MyController extends Controller 
                   with TransactionSupport 
                   with JsonConverterSupport 
                   with LoggerSupport

在这些特性中,我定义了一些可以直接在MyController使用的方法和字段。

但我的朋友说:当你extendswith特质时,它应该be a特质。

看看MyController ,它是一个Controller ,但它不是一个TransactionSupport ,不是一个JsonConverterSupport ,不是一个LoggerSupport ,所以它不应该with它们一起使用。

所以代码变成:

class MyController(tranSupport: TransactionSupport, 
                   jsonConverter: JsonConverterSupport, 
                   loggerSupport: LoggerSupport) extends Controller

但我对这段代码感觉不太好,这看起来很奇怪。

我看到trait在scala代码中大量使用,我什么时候应该使用它或者使用类来注入?

我会推荐你接口应该是形容词 虽然一些特征可能扮演一个类的一部分(因此,是名词并尊重“是一个”关系),但当用作mixin时,它们往往会扮演界面的一部分。

作为一个“形容词”,该特征将为他们所扩展的任何内容添加一个合格的属性。 例如,它们可能是ComparableSerializable

找到一个适合的形容词可能有点难度 - 你会用什么形容词来表示LoggerSupport - 所以不要觉得过分受到限制。 请注意,特质是完全错误的,因为它必然是一种“是一种”的关系。

不过,我会尽量避免使用特征来代替“has-a”关系。

我的意见是,它不一定to be它。 混合是一种与继承不同的概念。 即使在语法上它是相同的,但它并不意味着相同。 混合的典型用例就像你写的那样记录。 这并不意味着如果您的服务类混合了Logging特性, it is一个记录器。 这只是如何将功能组合到工作对象中的另一种方式。

奥德斯基建议,如果你不确定,你可以使用trait因为它们更灵活。 如果需要,您可以在将来将trait更改为class

有时当我觉得混合特性看起来不好时,我会使用这样的模块模式:

trait JsonConverterModule {

    protected def jsonConverter: JsonConverter

    protected trait JsonConverter {
      def convert(in: Json): Json
    }
  }

class MyController extends Controller with JsonConverterModule {
   private doSmth = jsonConverter.convert(...)
}

在这种情况下,MyController看起来更像是一个Controller,所有与Json相关的东西都隐藏在MyController'client'中

你的第一个特征示例是“蛋糕模式”,第二个例子是“构造函数注入”。 两者都是在Scala中进行依赖注入的完全有效的方法。 蛋糕模式功能强大,你可以注入类型成员,不同的特性可以很容易地相互通信(我们不必创建单独的对象并将它们传递给每个其他对象,通常需要setter注入而不是简单的构造函数注入),但是,必须在编译时实现类型,并且必须为每个特征组合实现单独的类。 构造函数注入允许您在运行时构建对象,并且可以针对大量组合进行更好的扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM