복붙노트

[SCALA] 스칼라의 형식 매개 변수로 표현 형식의 인스턴스를 인스턴스화하는 방법

SCALA

스칼라의 형식 매개 변수로 표현 형식의 인스턴스를 인스턴스화하는 방법

예:

import scala.actors._  
import Actor._  

class BalanceActor[T <: Actor] extends Actor {  
  val workers: Int = 10  

  private lazy val actors = new Array[T](workers)  

  override def start() = {  
    for (i <- 0 to (workers - 1)) {  
      // error below: classtype required but T found  
      actors(i) = new T  
      actors(i).start  
    }  
    super.start()  
  }  
  // error below:  method mailboxSize cannot be accessed in T
  def workerMailboxSizes: List[Int] = (actors map (_.mailboxSize)).toList  
.  
.  
.  

는 배우 항목이 있지만 클래스 일반적인 정의에 제약으로 "T는"배우의 하위 클래스입니다, "T"의 있습니다 알고있는 두 번째 오류 쇼를합니다.

어떻게이 코드는 (스칼라 2.8을 사용하여) 작업으로 수정 될 수 있습니까?

해결법

  1. ==============================

    1.편집 - 사과, 나는 단지 첫 번째 오류를 발견했습니다. 프로그램은 (유형 삭제를 통해) 컴파일 할 때 유형의 정보가 손실되기 때문에 런타임에 T를 인스턴스화의 방법은 없습니다

    편집 - 사과, 나는 단지 첫 번째 오류를 발견했습니다. 프로그램은 (유형 삭제를 통해) 컴파일 할 때 유형의 정보가 손실되기 때문에 런타임에 T를 인스턴스화의 방법은 없습니다

    당신은 건설을 달성하기 위해 일부 공장에서 통과해야합니다 :

    class BalanceActor[T <: Actor](val fac: () => T) extends Actor {
      val workers: Int = 10
    
      private lazy val actors = new Array[T](workers)
    
      override def start() = {
        for (i <- 0 to (workers - 1)) {
          actors(i) = fac() //use the factory method to instantiate a T
          actors(i).start
        }
        super.start()
      }
    } 
    

    다음과 같이 일부 배우 CalcActor와 함께 사용할 수 있습니다 :

    val ba = new BalanceActor[CalcActor]( { () => new CalcActor } )
    ba.start
    

    제쳐두고 : 당신은 때까지 대신에 사용할 수 있습니다 :

    val size = 10
    0 until size //is equivalent to:
    0 to (size -1)
    
  2. ==============================

    2.사용 매니페스트 :

    사용 매니페스트 :

    class Foo[A](a: A)(implicit m: scala.reflect.Manifest[A]) {
      def create: A = m.erasure.newInstance.asInstanceOf[A]
    }
    
    class Bar
    
    var bar1 = new Bar       // prints "bar1: Bar = Bar@321ea24" in console
    val foo = new Foo[Bar](bar1)
    val bar2 = foo.create    // prints "bar2: Bar = Bar@6ef7cbcc" in console
    bar2.isInstanceOf[Bar]   // prints "Boolean = true" in console
    

    BTW, 매니페스트 때문에주의해서 사용 2.7.X에 문서화되어있다. 동일한 코드 야간뿐만 아니라 2.8.0에서 작동합니다.

  3. ==============================

    3.이 일을 적절하고 안전한 방법은 지금있다. 스칼라 2.10 실제로 일반적인 유형을 사용하는 경우 삭제의 문제를 극복 할 수있게 TypeTags을 소개했다.

    이 일을 적절하고 안전한 방법은 지금있다. 스칼라 2.10 실제로 일반적인 유형을 사용하는 경우 삭제의 문제를 극복 할 수있게 TypeTags을 소개했다.

    다음과 같이 클래스의 파라미터를 할 수있게되었습니다 :

    class BalanceActor[T <: Actor :ClassTag](fac: () => T) extends Actor {
        val actors = Array.fill[T](10)(fac())
    }
    

    이렇게함으로써, 우리는 클래스가 인스턴스화 될 때 사용할 수 암시 ClassTag [T]를 요구하고있다. 컴파일러는 이러한 경우 상기 클래스 생성자로 ClassTag [T]를 통과하는 코드를 생성되도록한다. ClassTag [T]는 T에 대한 모든 종류의 정보를 포함하고, 컴파일시에 컴파일러에 사용할 수있는 동일한 정보 이것의 결과로 (사전에 삭제) 이제 구조에 우리를있게, 실행시에 사용할 수 있습니다 배열 [T].

    아직 할 수 없습니다 있습니다 :

    class BalanceActor[T <: Actor :ClassTag] extends Actor {
        val actors = Array.fill[T](10)(new T())
    }
    

    이 작동하지 않는 이유는 컴파일러가 클래스 T가 인수 없음의 생성자가 있는지 여부를 알 수있는 방법이 없다는 것입니다.

  4. ==============================

    4.당신 때문에 삭제의 이미 인스턴스화 T를 언급 한 바와 같이, 수 없습니다. 실행시에는 T.이 컴파일시에있는 대체 일이 C ++의 템플릿과 같은하지 않습니다가, 그리고 여러 클래스는 실제로 실제 사용에서 각 변화에 대해 컴파일됩니다.

    당신 때문에 삭제의 이미 인스턴스화 T를 언급 한 바와 같이, 수 없습니다. 실행시에는 T.이 컴파일시에있는 대체 일이 C ++의 템플릿과 같은하지 않습니다가, 그리고 여러 클래스는 실제로 실제 사용에서 각 변화에 대해 컴파일됩니다.

    매니페스트 솔루션은 흥미롭지 만 매개 변수를 필요로하지 않는 T의 생성자가 가정합니다. 당신은을지지 않습니다.

    다른 객체를 호출 할 수 있도록 두 번째 문제에 관해서는, 메소드 mailboxSize이 보호됩니다. 업데이트 : 이것은 단지 스칼라 2.8의 사실이다.

  5. from https://stackoverflow.com/questions/1305563/how-to-instantiate-an-instance-of-type-represented-by-type-parameter-in-scala by cc-by-sa and MIT license