Перемещение закрытого пакета - должен ли я считать этот двоичный файл несовместимым?

Из-за проблемы с именем пакета aux под Windows я перемещаю вспомогательный класс в иерархию пакетов моей библиотеки из

de.sciss.scalainterpreter.aux

в

de.sciss.scalainterpreter

Класс является частным для библиотеки, т.е. private[scalainterpreter] object Helper,

Теперь используя http://typesafe.com/technology/migration-manager, очевидно, он сообщает, что изменение не совместимо:

Found 2 binary incompatibiities
===============================
 * class de.sciss.scalainterpreter.aux.Helper does not have a correspondent
   in new version
 * object de.sciss.scalainterpreter.aux.Helper does not have a correspondent
   in new version

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

Правильный?

3 ответа

Решение

Легко увидеть, как встраивание может нарушить клиентский код, поскольку встроенный код по существу сливается с клиентским интерфейсом. Этот пример действительно запрашивает ошибку связи; мы можем экспериментировать и делать такие вещи, как javap | grep Helper, но на каком-то уровне вы должны позволить скалаку делать свою работу.

package lib {

  object Lib {
    //import util.Helper
    @inline def result = Helper.help
  }

  //package util {

  private [lib] object Helper {
    @inline def help = "Does this help?"
  }
//}
}

Образец невинно стоящего клиента:

package client

object Test {
  import lib.Lib
  def main(args: Array[String]) {
    println(Lib.result)
  }
}

Меняется пакет на пакет частного класса:

$ scala -cp "classes;target" client.Test
Does this help?

apm@halyard ~/tmp/taking-it-private
$ vi lib.scala

apm@halyard ~/tmp/taking-it-private
$ rm -rf classes/*

apm@halyard ~/tmp/taking-it-private
$ smalac -d classes -optimise lib.scala 

apm@halyard ~/tmp/taking-it-private
$ smala -cp "classes;target" client.Test
java.lang.ClassNotFoundException: lib.util.Helper$

Javap показывает почему. [А именно, вызов является встроенным, но он все еще хочет инициировать модуль.]

Я не следил за обсуждениями, но, например, есть ссылки на: https://github.com/scala/scala/pull/1133 и другие обсуждения ML о том, какие ожидания в отношении двоичной совместимости являются действительными. https://groups.google.com/forum/?fromgroups=

Вы не указываете, если Helper до переезда была уже частная посылка. Поэтому я рассмотрю оба случая:

  • Если это был уже пакет private:

    Я подозреваю, что менеджер миграции сообщает о несовместимости только потому, что она должна оставаться консервативной: пакеты открываются в Scala (как в Java), что означает, что клиентский код может очень хорошо определить пакет класса scalainterpreter, Итак, двигая HelperВы действительно сломаете этот класс.

    Однако давайте будем прагматичны: de.sciss.scalainterpreter.aux это ваш пакет (и так же должны быть их подпакеты), и никто не должен определять свои собственные классы там. С этой дополнительной предпосылкой, двигаясь Helper действительно бинарно-совместимое изменение к клиентскому скала- коду.

    Что касается клиентского Java- кода, он немного отличается, потому что даже если Helper пакет закрыт, его видимость все еще public что касается JVM, и, таким образом, компилятор java с радостью разрешит клиентскому коду доступ Helper (таким образом, клиентский Java-код вполне может получить доступ Helper, несмотря на то, что он объявлен частным пакетом).

  • Если он не был закрытым до переезда:

    Ну, удачи. Клиентский код вполне может получить доступ Helperи этот шаг наверняка сломает это. Как примечание, вы можете использовать небольшую хитрость, чтобы сделать изменение совместимым с источником, но, увы, не совместимым с двоичным кодом. Просто добавьте следующий файл:

    package de.sciss
    
    package object scalainterpreter {
      object aux {
        val Helper = _root_.de.sciss.scalainterpreter.Helper
      }
    }
    

С вышеизложенным, вы все еще можете получить доступ Helper как de.sciss.scalainterpreter.aux.Helperи он все еще компилируется под windows (в отличие от определения пакета aux, который не компилируется из-за зарезервированного значения как имени файла). Но опять же, это не двоичная совместимость, только совместимость с источником.

Проще говоря, нет причин, почему это не будет. Связь происходит вокруг подписей; поскольку рассматриваемый объект находится в области компиляции, клиенты не могут (или, скорее, не должны) использовать его, и поэтому двоичная совместимость не является проблемой.

Другие вопросы по тегам