LINUX.ORG.RU

[Scala]Вызвать конструктор параметризованного типа

 


0

0

Хочу написать полиморфную функцию для добавления значения в список. Делаю так:

def addObject[T](list:List[T]) : List[T] = { 
    val newObject = new T;
    newObject :: list
  }

Компилятор на это ругается вот так:

/home/ovk/sources/mine/./test.scala:43: error: class type required but T found
    val newObject = new T;
                        ^
one error found

Возможно ли вообще как-то сделать то, что я хочу?

★★★

Можно неявно передавать в функцию билдер, который и будет создавать объекты нужного типа.

dave ★★★★★
()
Ответ на: комментарий от dave

Например,

trait PuperBuilder[+T] {
  def create(): T
}

implicit def string2puperBuilder(lst: List[String]) = new PuperBuilder[String] {
  def create() = "New"
}

def addObject[T](list:List[T])(implicit builder: List[T] => PuperBuilder[T]): List[T] = {  
  val newObject = builder(list).create(); 
  newObject :: list 
} 

Проверка:

scala> addObject(List("1", "2"))
res0: List[java.lang.String] = List(New, 1, 2)

Только я передавал бы билдер напрямую, иначе каждый раз будет создаваться объект-оболочка. Это не .NET, где можно требовать от параметрического типа наличия конструктора по-умолчанию.

P.S. Скалу только начал изучать.

dave ★★★★★
()
Ответ на: комментарий от dave

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

dave ★★★★★
()
Ответ на: комментарий от Karapuz

> А скобачки в Scala не пишут?

Не роляет, там сначала вообще было new T(name)...

dave, изврат-то какой :)

ovk48 ★★★
() автор топика
Ответ на: комментарий от dave

>Это не .NET, где можно требовать от параметрического типа наличия конструктора по-умолчанию.

а что случиться, если этот конструктор приватный?

www_linux_org_ru ★★★★★
()

Так, как в ОП-посте это сделать невозможно потому что type erasure. А делать надо так:

import scala.reflect.Manifest

scala> def addObject[T](list: List[T])(implicit m: Manifest[T]) = {
     val newObject = m.erasure.newInstance
     newObject :: list
}

Проверяем:

scala> val l = List("asdf")
l: List[java.lang.String] = List(asdf)

scala> addObject(l)
res17: List[Any] = List(, asdf)
Zenom ★★★
()
Ответ на: комментарий от Zenom

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

Zenom ★★★
()
Ответ на: комментарий от dave

> будет еггог, надо думать

интересно также, что будет в скале — надеюсь, что ЕГГОГ будет во время компиляции...?

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Zenom

>res17: List[Any] = List(, asdf)

похоже, ты недокопипастил, и получился List[Any]

надо = m.erasure.newInstance.asInstanceOf[T]

З.Ы. эта вещь выглядит подозрительно — того и гляди, кинет исключение в рантайме

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от ovk48

> dave, изврат-то какой :)

чувак, а *ты* подумал, что будет, если у тебя у Т конструктор по умолчанию будет приватный?

тебе с этим надо считаться, так что implicit тут неизбежен, вопрос только какой конкретно

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.