Какие вложенные/неактивные пакеты в Scala 2.8?

В Scala 2.7 я мог бы написать:

package com.acme.bar

class Bar

.

package com.acme.foo

class Foo {
  new bar.Bar
}

Это не компилируется в Scala 2.8 - однако это делает:

package com.acme 
package bar

class Bar

.

package com.acme
package foo

class Foo {
  new bar.Bar
}
  • Какова была мотивация для этого?
  • Каков точный смысл в отношении сферы видимости и видимости?
  • Когда следует использовать одну форму над другой?

Ответы

Ответ 1

В списках рассылки было несколько длительных обсуждений. См. этот поток для проблемы и этот поток для решения.

Что касается значения, то только

package A
package B
Форма

откроет область для A, что делает элементы A видимыми без префикса. Обычно вы используете эту форму, если ваш проект состоит из нескольких подпакетов, которые ссылаются друг на друга. С другой стороны, вы должны использовать форму

package A.B.C

Если вы хотите интегрировать C в иерархию пакетов и не намереваться напрямую обращаться к другим членам A или B. Типичный случай

package net.myorg.myproject

Здесь вы не хотите быть уязвимым для возможности, чем кто-либо другой определил net.java, который затеняет уровень java уровня корня. В Scala 2.7 вы можете предотвратить это с помощью импорта _root_. Но это уродливо, и, чтобы быть в безопасности, вам придется делать это почти везде. Таким образом, настоящее решение намного лучше, ИМО.

Ответ 2

Спасибо за ответы! Позвольте мне добавить две небольшие точки, и мы закончили!

Видимость

Разница между вложенными и неустановленными пакетами применяется только к области охвата. Видимость всегда основана на вложенных пакетах.

package A

private[A] trait Secret

Это работает:

package A
package B

trait AB extends Secret

Так делает это:

package A.B

trait AB extends A.Secret

В обоих случаях структура интерпретируется как:

package A {
  trait Secret
  package B {
     //...
  }
}

Scoping

Сравните это с scoping, в котором вы могли бы представить эту интерпретацию для неустановленных пакетов:

package A {
  private [A] trait Secret
}

package `A.B` {
   trait AB extends A.Secret

}

Смешать и сопоставить

Вы можете произвольно смешивать и сопоставлять вложенный и неинтересный пакет:

package com.acme.project
package util.shazam
package blerg

Ответ 3

Разве это не дает вам больше контроля над тем, что импортируется? Например, если были пакеты:

package com.acme.foo.client
package com.acme.client

А затем изнутри Foo не было ли раздражающей двусмысленности, о которой упоминалось client? Например, если вы хотите сделать подстановочный импорт из Foo:

class Foo {
  import client._ //what is being imported?
}

Это может быть гораздо более проблематичным, если вместо client у нас был пакет com.acme.java:

class Foo {
    val jul = new java.util.LinkedList //compile error; cannot find util
}