Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Class 如何决定使用trait来';与';或类到';注入';?_Class_Scala_Traits - Fatal编程技术网

Class 如何决定使用trait来';与';或类到';注入';?

Class 如何决定使用trait来';与';或类到';注入';?,class,scala,traits,Class,Scala,Traits,在编写scala代码时,我很难选择特征或类 首先,我有一个控制器,具有以下几个特点: class MyController extends Controller with TransactionSupport with JsonConverterSupport with LoggerSupport 在这些特性中,我定义了一些可以直接在MyController中使用的方法和字段

在编写scala代码时,我很难选择
特征

首先,我有一个控制器,
具有以下几个特点:

class MyController extends Controller 
                   with TransactionSupport 
                   with JsonConverterSupport 
                   with LoggerSupport
在这些特性中,我定义了一些可以直接在MyController中使用的方法和字段

但是我的朋友说:当你
扩展了
或者
一种特质时,它应该是一种
那种特质

看看
MyController
,它是
控制器
,但它不是
交易支持
,不是
JsonConverterSupport
,也不是
日志支持
,因此它不应该与
一起使用

因此,代码变成:

class MyController(tranSupport: TransactionSupport, 
                   jsonConverter: JsonConverterSupport, 
                   loggerSupport: LoggerSupport) extends Controller
但是我对这段代码感觉不好,它看起来很奇怪


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

我的观点是,它没有
成为它。混入与继承是不同的概念。即使在句法上它是相同的,但并不意味着相同。混入的典型用例是像您所写的那样记录日志。这并不意味着如果您的服务类混合了
日志记录
特性,那么
就是一个日志记录者。这只是将功能组合到工作对象中的另一种方式

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

我会让您参考。尽管某些特征可能扮演一个类的角色(因此,它们是名词并尊重“is-a”关系),但当用作混搭时,它们往往扮演接口的角色

作为一个“形容词”,特质将为其扩展的内容添加限定属性。例如,它们可能是可比较的
或可序列化的

要找到一个合适的形容词可能有点困难——你会用哪个形容词来形容
LoggerSupport
?——所以,不要觉得自己受到了太多的约束。只是要意识到,将特质的东西视为必然的“是一种”关系是完全错误的


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

有时当我觉得混合特质看起来不太好时,我会使用如下模块模式:

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看起来更像一个控制器,所有与Json相关的内容都隐藏在MyController的“客户端”中。

您的第一个带有traits的示例是“蛋糕模式”,第二个示例是“构造函数注入”。这两种方法都是在Scala中进行依赖项注入的非常有效的方法。cake模式功能强大,可以注入类型成员,不同的trait可以很容易地相互对话(我们不必创建单独的对象并将它们传递给其他对象,通常需要setter注入而不是简单的构造函数注入),等等。但是,类型必须在编译时实现,每一个特征组合都必须实现一个单独的类别。构造函数注入使您能够在运行时构建对象,并能更好地扩展大量组合