从2.10开始,-Xlint抱怨在package对象内部定义的类。但是为什么呢?在包对象中定义一个类应该完全等同于在一个单独的包中定义同名的类,只是方便多了。
在我看来,Scala中一个严重的设计缺陷是不能在文件的顶层放置除类实体之外的任何东西(例如变量声明、函数定义)。相反,您必须将它们放入一个单独的“包对象”中(通常是在package.scala中),与它们所属的其余代码分开,这违反了一个基本的编程规则,即概念上相关的代码也应该是物理相关的。我看不出为什么Scala在概念上不允许在顶层允许任何它在较低级别允许的东西,并且任何非类的东西都会自动放到package对象中,这样用户就永远不需要担心它了。
例如,在我的示例中,我有一个util包,在它下面有许多子包(util.io、util.text、util.time、util.os、util.math、util.distances等)。它将语义上相关的函数、类,有时还有变量的异构集合组合在一起。目前,我将所有不同的函数、类等存储在一个package object中,该文件位于util目录下的一个名为io.scala或text.scala的文件中。这很好用,而且非常方便,因为函数和类可以混合在一起,例如,我可以这样做:
package object math {
// Coordinates on a sphere
case class SphereCoord(lat: Double, long: Double) { ... }
// great-circle distance between two points
def spheredist(a: SphereCoord, b: SphereCoord) = ...
// Area of rectangle running along latitude/longitude lines
def rectArea(topleft: SphereCoord, botright: SphereCoord) = ...
// ...
// ...
// Exact-decimal functions
class DecimalInexactError extends Exception
// Format floating point value in decimal, error if can't do exactly
formatDecimalExactly(val num: Double) = ...
// ...
// ...
}如果没有这一点,我将不得不根据fun和class而不是语义来拆分代码,这很不方便。我想,另一种选择是把它们放在一个普通的对象中--这有点违背了最初拥有包对象的目的。
发布于 2013-06-24 20:56:28
但是为什么呢?在包对象内定义类应该完全等同于在具有相同名称的单独包内定义类,
确切地说。语义(目前)是相同的,所以如果你喜欢在包对象中定义一个类,应该有一个很好的理由。但现实是,至少有一个很好的理由不(继续阅读)。
除了更方便之外
这怎么会更方便呢?如果您正在执行此操作:
package object mypkg {
class MyClass
}您也可以执行以下操作:
package mypkg {
class MyClass
}您甚至可以在该过程中节省几个字符:)
现在,不要过度使用包对象的一个好的和具体的理由是,尽管包是开放的,但包对象是而不是。一种常见的方案是在几个项目之间分派代码,每个项目在同一个包中定义类。这里没有问题。另一方面,包对象(就像任何对象一样)是封闭的(正如规范所说的“每个包只能有一个包对象”)。换句话说,您只能在项目的one中定义包对象。如果您试图在两个不同的项目中为同一个包定义一个包对象,则会发生一些不好的事情,因为您实际上会得到同一个JVM类的两个不同版本(在我们的例子中,您最终会得到两个"mypkg.class“文件)。根据情况的不同,编译器可能会抱怨找不到您在package对象的第一个版本中定义的内容,或者得到“错误的符号引用”错误,甚至可能是运行时错误。这是package对象的一般限制,因此您必须意识到这一点。在包对象中定义类的情况下,解决方案很简单:不要这样做(考虑到与仅将类定义为顶级相比,您不会获得任何实质性的好处)。对于类型别名、val和vars,我们没有这样的奢侈,所以在这种情况下,关键是权衡语法上的便利性(与在对象中定义它们相比)是否值得,然后注意不要定义重复的包对象。
发布于 2014-01-09 03:45:24
我还没有找到一个很好的答案来解释为什么这个语义等价的操作会生成lint警告。我认为这是一个毛线虫。我发现不能放在一个package对象内(而不是放在一个普通的package内)的唯一一件事是一个实现main (或extends App)的对象。
请注意,-Xlint还抱怨在package对象中声明的隐式类,即使它们不能在package作用域中声明。(有关隐式类的规则,请参阅http://docs.scala-lang.org/overviews/core/implicit-classes.html。)
发布于 2014-01-09 10:09:17
我想出了一个诀窍,既可以享受包对象的所有好处,又不会抱怨被弃用。代替
package object foo {
...
}你可以做到
protected class FooPackage {
...
}
package object foo extends FooPackage { }工作相同,但没有任何抱怨。明显的迹象表明,投诉本身是假的。
https://stackoverflow.com/questions/17270003
复制相似问题