我觉得我应该在此之前加上我用sbt构建项目的事实。
我的问题是,如果在编译时一个方法返回一个无类型的东西,在我调用该方法的文件中,只要我使用类型推断,一切都会编译。一旦我尝试将未导入的类型分配给我使用函数的返回值创建的var / val,我就会遇到编译器错误。
假设我在两个包中有两个类。包App
中的课程main
和课程Imported
中的课程libraries
。让我们进一步说,我们在包main中有一个类ImportedFactory
,并且该类有一个方法来创建Imported类型的对象。
这段代码编译得很好:
class App() {
// method return object of type Imported
val imp = ImportedFactory.createImportedObject()
}
这不是:
class App() {
// method return object of type Imported
val imp : Imported = ImportedFactory.createImportedObject()
}
这又一次:
import libraries.Imported
class App() {
// method return object of type Imported
val imp : Imported = ImportedFactory.createImportedObject()
}
这似乎是一种相当奇怪的行为。对于编译时带类型推断的语言来说这是正常的吗?由于我的无知,我还没注意到go / C ++中的语言?
两种有效方法中的一种(导入和显式类型与感染)相比有哪些优点/缺点? (当然,期望一个更明确,更冗长,另一个更短)
这是黑魔法还是Scala编译器以相当直接的方式完成这些推论?
答案 0 :(得分:5)
导入的唯一功能是在当前范围内提供不完全限定的名称。你也可以这样写:
class App() {
val imp: libraries.Imported = ImportedFactory.createImportedObject()
}
您import libraries.Imported
的原因是让您可以编写较短的名称Imported
。如果您让编译器推断出类型,则不要在代码中提及类型,因此您不必导入其较短的名称。
顺便说一句:这与C ++中的动态转换无关。代码中唯一可行的机制是类型推断。
答案 1 :(得分:1)
注意:使用术语类型推断
,您将获得更好的搜索结果使用val imp = ImportedFactory.createImportedObject()
,您可以让编译器根据类型推断确定imp
应该是什么类型。无论createImportObject
返回什么类型,都是imp
的类型。
使用val imp : Imported = ImportedFactory.createImportedObject()
,您明确声明imp
是Imported
。但编译器不知道你的意思,除非你......导入......它。
这两种方法都有其优点:
推断类型
推断类型非常适用于将类型显而易见的代码放在一起时:
val i = 1 // obviously `i` is an int
val j = i + 10 // obviously still an int
对于当地的vars / vals来说,这种类型的写入也太痛苦了
val myFoo: FancyAbstractThing[TypeParam, AnotherTypeParam[OhNoMoreTypeParams]] = ...
// vs
val myFoo = FancyThingFactory.makeANewOne()
缺点是,如果您允许公共def / val具有推断类型,则确定如何使用该方法可能更加困难。因此,省略类型注释通常仅用于简单常量,而在“客户端代码”不必查看的本地val / vars中。
显式类型
如果你想编写库代码(即public vals / defs),那么惯例就是明确地输入它们。
可能最简单的原因是因为:
def myLibraryMethod = {
// super complicated implementation
}
比
更难理解def myLibraryMethod: String = {
// super complicated implementation
}
明确键入代码的另一个好处是,当您希望公开一个不太具体的类型而不是实际值时:
val invalidNumbers: Set[Int] = TreeSet(4, 8, 15, 16, 23, 42)
在此示例中,您不希望客户端代码需要关心您的invalidNumbers
实际上是TreeSet
。这是一个实现细节。在这种情况下,你隐藏了一些信息,这些信息虽然是真的,但会分散注意力。