Что такое вложенные / не вложенные пакеты в 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. Какова была мотивация для этого?
  2. Каково точное значение с точки зрения объема и видимости?
  3. Когда я должен использовать одну форму поверх другой?

3 ответа

Решение

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

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

package A
package B

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

package A.B.C

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

package net.myorg.myproject

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

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

видимость

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

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 {
     //...
  }
}

Обзорный

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

package A {
  private [A] trait Secret
}

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

}

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

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

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

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

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
}
Другие вопросы по тегам