2013-09-17 3 views
3

У меня есть несколько вопросов о генераторах scala и значениях параметров по умолчанию.Scala: Общий массив с значением параметра по умолчанию в конструкторе

Предположим, у меня есть следующее определение класса (где Stack [E] является признаком)

class ImmutableStack[E](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends Stack[E] 

Когда я пытаюсь скомпилировать этот код дает две ошибки:

scala: cannot find class tag for element type E 
class ImmutableStack[E <: Any](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends SedgewickStack[E] { 
                   ^

А:

scala: not found: value capacity 
class ImmutableStack[E <: Any](capacity: Int = 10, elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) extends SedgewickStack[E] { 
                       ^

Может кто-нибудь объяснить мне:

  1. Почему параметр мощности недоступен для других параметров в определении конструктора?
  2. Почему ClassTag ev недоступен для значения параметра по умолчанию i.e new Array[E](capacity)?

Когда я удаляю значение по умолчанию для параметра elem - все работает нормально.

Заранее благодарим за любой ответ.

+2

Возможно, это не полный ответ, но: я не думаю, что 'capacity' действительно находится в области видимости внутри объявления конструктора. В этом отношении я не знаю, может ли какой-либо язык допускать перекрестные ссылки на конструктор или функциональные параметры; вы можете получить доступ к ним только в теле. –

+3

@ViktorSeifert: ссылка на «емкость» не является проблемой. Вам просто нужно переместить его в группу дополнительных параметров. Это отлично работает 'def test (a: Int) (b: Int = a) = a + b; тест (1)() '. Но вы не можете получить доступ к параметру из следующей группы ('ev'). – senia

+0

@senia Это работает для конструкторов? –

ответ

1

Вы можете использовать только значения из предыдущих списков аргументов для значений по умолчанию в конструкторах и методах, а не из того же самого:

class ImmutableStack[E <: Any](capacity: Int = 10)(elems: Array[E] = new Array[E](capacity))(implicit ev: ClassTag[E]) 

Чтобы обойти неспособность использовать неявный класс тег, лучшее, что я могу предложить

class ImmutableStack[E <: Any : ClassTag](capacity: Int = 10)(elems: Array[E] = null) { 
    val realElems = if (elems != null) elems else new Array[E](capacity) 
} 
+0

Спасибо за подсказку. Я также использовал тот же подход со значением по умолчанию для параметра elems. Но правильно ли мне, что невозможность построить массив с параметром generic type в качестве значения параметра по умолчанию определяется тем, что неявный ClassTag предоставляется только как последний список аргументов и не доступен в предыдущих списках аргументов? – JohnGray

+1

Да, я так считаю. –

Смежные вопросы