2012-08-07 14 views
11

型パラメータではなく抽象型を使用します。私の一般的なクラスのコンストラクタでスカラクラスのコンストラクタと抽象型

、私はジェネリック型のパラメータを持つようにしたいが、コードはコンパイルされません:

class SomeOtherClass(val s: S){ 
    type S 
} 

をScalaのコンパイラエラーがさ「が見つかりません:タイプS」

私は抽象型ではなく型パラメータを使用する場合

、それは動作します:私が持っているしたい場合は

class SomeClass[T](val t: T){ 
    //... 
} 

いScalaの力は、私は、抽象型ではなく、型パラメータを使用しますコンストラクタの汎用パラメータ?

これを行う別の方法はありますか?

答えて

3

この場合、ジェネリック型パラメータを使用する必要があります。クラスの外側で型を宣言することで回避することができますが、ラッパーをインスタンス化してからオブジェクトを生成する必要があり、かなり醜い状態になります。

trait FooDef { 
    type T 
    class Foo(val x: T) 
} 
val ifd = new FooDef { type T = Int } 
val ifoo = new ifd.Foo(5) 
val sfd = new FooDef { type T = String } 
val sfoo = new sfd.Foo("hi") 
def intFoos(f: fd.Foo forSome { val fd: FooDef {type T = Int} }) = f.x + 1 
0

コンパイラはどのタイプを使用するべきですか?いずれかの型を直接指定する必要がありますが、それは意味をなさないでしょう。それを機能させる一つの方法がありますが、それがあなたを助けるとは思いません。

class SomeClass(s: SomeClass#S) { 
    type S 
} 

しかし、SomeClass#Sは定義されていないため、インスタンスはありません。

+0

面白いことに、これはあなたが '新しいSomeClass(5.asInstanceOf [SomeClass#S]){type S = Int}'インスタンスを作成することを可能にします。安全性がないことに注意してください.Sはまだキャストでは未定義です。 – Kaito

+0

基本的にそれを正しく行うには、私は他の2つの答えを見なければなりませんか? –

+0

@AntKutscheraはい。 – Nicolas

0

多分このようなものが欲しいですか?このようにして、AbstractFooFactoryの複数のインスタンスをそれぞれ異なる値のFooを生成することができます。

trait AbstractFooFactory { 
    type S 
    def makeFoo(s:S):Foo 
    class Foo(val s:S) {} 
} 

object StringFooFactory extends AbstractFooFactory { 
    override type S = String 
    override def makeFoo(s:String) = new Foo(s) 
} 

val b = StringFooFactory.makeFoo("bar") 
val s:String = b.s 
1

抽象タイプを指定しない場合、クラスは抽象クラスである必要があります。したがって、パラメータはまったく必要ありません。抽象型と同等では次のようになります。

使用-サイトで次に
abstract class SomeOtherClass { 
    type S 
    val s: S 
} 

:パラメータなし

val x = new SomeOtherClass { 
    type S = String 
    val s = "abc" 
} 

、ここで抽象クラスは、特色に相当します。制限の少ない(1つの基本クラスのみを拡張することができる)ため、形質を使うほうがよいです。

関連する問題