斯卡拉,为什么我不需要导入推导类型

斯卡拉,为什么我不需要导入推导类型

问题描述:

我觉得我应该以这样一个事实开头,即我正在用sbt构建我的项目。斯卡拉,为什么我不需要导入推导类型

我的问题是,如果在编译时某个方法返回某个未导入类型的东西,则在我调用该方法的文件中,只要我使用类型推断,就会编译所有内容。一旦我尝试将我的函数的返回值创建的var/val分配给unimported类型,我得到一个编译器错误。

可以说我有两个包中的两个类。包中的类为App,包main和类Importedlibraries。让我们进一步说,我们在包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++中?

两种有效方法之一(导入&显式类型与传染)有优点/缺点比其他? (当然,期望的是一个更明确和详细,另一个更短)

这是黑魔法还是斯卡拉编译器以相当直接的方式完成这些扣除?

注:您会得到更好的搜索结果与术语类型推断

随着val imp = ImportedFactory.createImportedObject()你让编译器弄清楚什么类型的imp应根据类型推断。无论什么类型的createImportObject返回,这就是imp类型。

使用val imp : Imported = ImportedFactory.createImportedObject()您明确指出impImported。但编译器不知道你的意思,除非你......导入......它。

两种方法各有优点:

推断类型

推断类型,当你扔在一起的代码,其中类型应该是显而易见的是巨大的:

val i = 1 // obviously `i` is an int 
val j = i + 10 // obviously still an int 

这也是很大的对于当地的瓦尔/瓦尔型这种类型会太痛苦写

val myFoo: FancyAbstractThing[TypeParam, AnotherTypeParam[OhNoMoreTypeParams]] = ... 
// vs 
val myFoo = FancyThingFactory.makeANewOne() 

缺点是,如果您已允许公共def/val具有推断类型,则确定如何使用该方法可能会更困难。由于这个原因,省略类型注释通常只用于简单的常量,并且在“客户代码”不必看的本地vals/vars中。

明确的类型

当你想要写库上下的代码(即公共丘壑/ DEFS),惯例是显式输入。

可能就是这个最简单的原因是因为这样的:

def myLibraryMethod = { 
    // super complicated implementation 
} 

是很难理解比

def myLibraryMethod: String = { 
    // super complicated implementation 
} 

另一个好处明确,输入你的代码是当你想揭露less-具体类型比实际值多:

val invalidNumbers: Set[Int] = TreeSet(4, 8, 15, 16, 23, 42) 

在这个例子中,你不要w蚂蚁客户端代码需要注意,您的invalidNumbers实际上是一个TreeSet。这是一个实现细节。在这种情况下,你隐藏了一些信息,虽然是真的,但会分散注意力。

导入的唯一事情就是在当前范围内提供一个不完全限定的名称。你也可以同样这样写:

的原因,你import libraries.Imported是为了使较短的名称Imported可为你写。如果你让编译器推断出这个类型,你就不会在代码中提到这个类型,所以你不必导入它的较短的名字。

顺便说一下:这与C++中的动态转换无关。在你的代码中工作的唯一机制是类型推断。

+0

我挪用了动态铸造这个术语,这可能确实对我的问题造成了很多混淆(并且缺乏建议),对不起。 – George