Головоломка - выставление публичного подчиненного частного члена с пользовательским типом - PullRequest
8 голосов
/ 02 января 2012

Я хотел бы сделать что-то вроде этого (пример упрощен, но содержит все важные части):

class Master
{
  type DataType = Int
  var counter : DataType = 0
}

class Slave(private val master : Master)
{
  val counter = master.counter  // (*)
}

И здесь (*) я получаю ошибку:

личное значение master выходит за пределы определяющей области как часть типа Slave.this.master.DataType

val counter = master.counter

Я понимаю ошибку, но не понимаюпонять причину - тип является частью класса Master, а не объекта master, поэтому важно, чтобы класс был закрытым, а не объектом.Ну, по крайней мере, в теории.

Легко сделать быстрый обходной путь:

  val counter : Master#DataType = master.counter  

Но я считаю, что это явная версия точно такого же кода, как и раньше, это "только"занимает больше печатать.Это особенность тогда?

ВОПРОС:

Может ли тип (в данном случае DataType) зависеть от объекта, а не от класса (то есть определения типа для экземпляра класса) в Scala?

1 Ответ

14 голосов
/ 02 января 2012

Вы ошибаетесь, когда думаете

это явная версия того же кода, что и раньше

Master#DataType и master.DataType - это два разных типа.

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

Master#DataType - это тип любого экземпляра DataType для любого внешнего объекта (эквивалент Master.DataType в Java).

ОТВЕТИТЬ НА КОММЕНТАРИЙ:

Элементы типа могут быть переопределены в подклассе (включая анонимный подкласс, содержащий только один объект), но только с помощью совместимого типа. И в вашем примере DataType уже конкретен в Master, поэтому единственный совместимый класс с ним - это сам. Так что-то вроде

val a = new Master {
  override type DataType = String
}

не проверяет тип, что имеет смысл: вы получите var counter: String = 0, что является чепухой. Но

val a = new Master {
  override type DataType = Int
}

будет работать (но не слишком полезно).

Так что имеет смысл переопределять abstract членов типа. Но они проверяются по типу так же, как и внутренние классы, поэтому a.DataType обычно не считается таким же, как b.DataType - даже если они на самом деле не могут отличаться!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...