Почему люди определяют класс, черту, объект внутри другого объекта в Scala?

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

26
задан Sawyer 13 January 2011 в 15:04
поделиться

2 ответа

До версии 2.8 вам приходилось выбирать между пакетами и объектами. Проблема с пакетами заключается в том, что они не могут содержать методы или значения самостоятельно. Таким образом, вы должны поместить все это в другой объект, который может стать неловким. Обратите внимание:

object Encrypt {
  private val magicConstant = 0x12345678
  def encryptInt(i: Int) = i ^ magicConstant
  class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
    def hasNext = ii.hasNext
    def next = encryptInt(ii.next)
  }
}

Теперь вы можете import Encrypt._ и получить доступ к методу encryptInt, а также к классу EncryptIterator. Удобно!

Напротив,

package encrypt {
  object Encrypt {
    private[encrypt] val magicConstant = 0x12345678
    def encryptInt(i: Int) = i ^ magicConstant
  }
  class EncryptIterator(ii: Iterator[Int]) extends Iterator[Int] {
    def hasNext = ii.hasNext
    def next = Encrypt.encryptInt(ii.next)
  }
}

Это не огромная разница , но это заставляет пользователя импортировать как encrypt._, так и encrypt.Encrypt._ или должен сохранять писать Encrypt.encryptInt снова и снова. Почему бы просто не использовать объект вместо этого, как в первом шаблоне? (На самом деле нет никакого снижения производительности, поскольку вложенные классы на самом деле не являются внутренними классами Java; насколько это известно JVM, это просто обычные классы, но с причудливыми именами, которые говорят вам, что они вложенные.)

В 2.8 вы можете получить свой торт и съесть его: назовите вещь как объект пакета, и компилятор перезапишет код для вас, так что на самом деле он выглядит как второй пример под капотом (за исключением объекта Encrypt ] на самом деле называется package внутренне), но ведет себя как первый пример с точки зрения пространства имен - значения vals и def находятся тут же, без необходимости дополнительного импорта.

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

(PS Пожалуйста, не пытайтесь фактически зашифровать что-либо таким образом, кроме как в качестве примера или шутки!)

22
ответ дан Rex Kerr 13 January 2011 в 15:04
поделиться

Это может быть и другое. Среди прочего, экземпляр внутреннего класса / свойства имеет доступ к переменным своего родителя. Внутренние классы должны быть созданы с родительским экземпляром, который является экземпляром внешнего типа.

В других случаях это, вероятно, просто способ группировки тесно связанных вещей, как в вашем object примере. Обратите внимание, что признак LocParam запечатан, что означает, что все подклассы должны находиться в одном и том же модуле / файле компиляции.

3
ответ дан sblundy 13 January 2011 в 15:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: