[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.편집 - 사과, 나는 단지 첫 번째 오류를 발견했습니다. 프로그램은 (유형 삭제를 통해) 컴파일 할 때 유형의 정보가 손실되기 때문에 런타임에 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.사용 매니페스트 :
사용 매니페스트 :
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.이 일을 적절하고 안전한 방법은 지금있다. 스칼라 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.당신 때문에 삭제의 이미 인스턴스화 T를 언급 한 바와 같이, 수 없습니다. 실행시에는 T.이 컴파일시에있는 대체 일이 C ++의 템플릿과 같은하지 않습니다가, 그리고 여러 클래스는 실제로 실제 사용에서 각 변화에 대해 컴파일됩니다.
당신 때문에 삭제의 이미 인스턴스화 T를 언급 한 바와 같이, 수 없습니다. 실행시에는 T.이 컴파일시에있는 대체 일이 C ++의 템플릿과 같은하지 않습니다가, 그리고 여러 클래스는 실제로 실제 사용에서 각 변화에 대해 컴파일됩니다.
매니페스트 솔루션은 흥미롭지 만 매개 변수를 필요로하지 않는 T의 생성자가 가정합니다. 당신은을지지 않습니다.
다른 객체를 호출 할 수 있도록 두 번째 문제에 관해서는, 메소드 mailboxSize이 보호됩니다. 업데이트 : 이것은 단지 스칼라 2.8의 사실이다.
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
'SCALA' 카테고리의 다른 글
[SCALA] 문자열에 FlatMap 대지도 (0) | 2019.11.15 |
---|---|
[SCALA] 스칼라 2.10 반사, 나는 경우 클래스의 경우 클래스, 즉 필드 목록에서 필드 값을 추출 어떻게 (0) | 2019.11.15 |
[SCALA] 때 @uncheckedVariance 스칼라에 필요하고, 왜 GenericTraversableTemplate에 사용됩니까? (0) | 2019.11.15 |
[SCALA] 왜 보조 기술은 타입 수준의 계산에 필요합니까? (0) | 2019.11.15 |
[SCALA] 왜 스칼라 특성은 클래스를 확장 할 수 있습니다? (0) | 2019.11.15 |