Pergunta

Eu estou tentando escrever algum código Scala que precisa fazer algo como:

class Test[Type] { 
   def main {
       SomeFunc classOf[Type]
       val testVal: Type = new Type()
    }
 }

e está falhando. Eu, obviamente, não estou entendendo alguma coisa sobre parâmetros genéricos Scala. Claramente, o mal-entendido é que, em C ++, modelos essencialmente funcionam como substituições de corda, tão novo Type () funcionará enquanto a classe que está sendo passado em tem um construtor padrão. No entanto, em Scala, tipos diferentes tipos de objetos.

Foi útil?

Solução

Como salienta, C ++ tem modelos. Em suma, C ++ diz que "não é um teste para todos os tipos de T tais que compila teste." Isso torna mais fácil para adicionar implicitamente restrições em T, mas no lado de baixo Eles são implícita e pode ser difícil para um usuário de sua classe a compreender sem ler código.

polimorfismo paramétrico de Scala (aka genéricos) trabalho muito mais como ML, Haskell, Java e C #. Em Scala, quando você escreve "classe de teste [T]" você está dizendo "para todos T existe um tipo de teste [T]", sem restrição. Isso é mais simples de raciocinar sobre formalmente, mas isso não significa que você tem que ser explícito sobre restrições. Por exemplo, no Scala você pode dizer "classe de teste [T <: Foo]" para dizer que T deve ser um subtipo de Foo.

C # tem uma maneira de adicionar uma restrição a T em relação construtores, mas infelizmente Scala não.

Há um par de maneiras de resolver o seu problema no Scala. Um deles é typesafe mas um bt mais detalhado. O outro não é typesafe.

Os typesafe forma se parece com

class Test[T](implicit val factory : () => T) {
  val testVal = factory
}

Em seguida, você pode ter um corpo de fábricas para tipos úteis em seu sistema

object Factories {
  implicit def listfact[X]() = List[X]()
  implicit def setfact[X]() = Set[X]()
  // etc
}

import Factories._
val t = new Test[Set[String]]

Se os usuários de sua necessidade biblioteca suas próprias fábricas, em seguida, eles podem adicionar seu próprio equivalente do objeto fábricas. Uma vantagem desta solução é que qualquer coisa com uma fábrica pode ser usado, se há ou não um construtor sem argumento.

O não-tão-typesafe maneira usos reflexão e uma característica em Scala chamados manifestos que são uma maneira de contornar uma restrição Java quanto ao tipo apagamento

 class Test[T](implicit m : Manifest[T]) {
   val testVal = m.erasure.newInstance().asInstanceOf[T]
 }

Com esta versão você ainda write

class Foo
val t = new Test[Foo]

No entanto, se há construtor não não-arg disponível você obter uma exceção de tempo de execução em vez de um tipo estático erro

scala> new Test[Set[String]] 
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top