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