2012-02-10 9 views
7

ネストされたオブジェクトを引数としてとるメソッドを作成する方法を理解しようとしています。私は、オブジェクトとそのような何かをしようとした場合に代わりに私が得る、しかしエラースカラのネストされたオブジェクトのタイプは何ですか

scala> class Outer { 
| class Inner 
| def method(i:Outer#Inner) = { "inner class" } 
| } 
defined class Outer 

:ネストされたクラスのために私は次の操作を行うことができます

scala> class Outer { 
| object Inner 
| def method(i:Outer#Inner) = { "inner object" } 
| } 
<console>:11: error: type Inner is not a member of Outer 
    def method(i:Outer#Inner) = { "inner object" } 

をどうすべきかの引数の型方法はこれを達成することですか?また、私はInnerオブジェクトのタイプを参照したいと思っていますAnyと言う引数を一般化していません。

答えて

12

Innerはオブジェクトであるため、型ではなく、型として使用できません。 InnerのタイプはInner.typeです。それは、あなたの例では意味します。残念ながら、Outerの各インスタンスには独自のInnerオブジェクトがあり、タイプがOuter#Inner.typeは安定していないため使用できません。回避策は、this.Inner.typeを使用することです。

def method(i:this.Inner.type) = { "inner object" } 

しかし、それはあなたが唯一のパラメータとして、あなたがmethodを呼び出しているインスタンスの内部オブジェクトを渡すことができることを意味します。

+0

これはコンパイルされません。 –

+1

Oups、あなたはOuterの代わりにこれを使う必要があります。私はそれを説明するために依存型の説明をもう一度読まなければなりません。 – Nicolas

+0

はい、これは機能します!また、Outerクラスの外で定義されたメソッドでInnerを使うために、私はOuterで定義することができます: 'type InnerType = this.Inner.type'そして、' defメソッド(i:Outer#InnerType) = "foo" ' –

7

(REPLで)ここで何が起こっているのか説明するための簡単な例:

object A 
def foo(a : A) = "Does not compile" 
def bar(a : A.type) = "Does compile!" 
bar(A) // returns "Does compile!" 

ニコラスが言うように、インナータイプではないので、あなたはそのように使用することはできません。

:すべての後に、唯一のそれのがあります - 私たちは直接インナーを参照しますので、これは、少し無意味である

class Outer(i : Int) { 
    object Inner { 
    def getI : Int = i 
    } 
    def foo(x : Inner.type) = x.getI 
} 

あなたのモチベーションを理解しようと、私はこのような何かを思い付きました

class Outer(i : Int) { 
    object Inner { 
    def getI : Int = i 
    } 
    def foo = Inner.getI 
} 

私はあなたがしたいことは、Outerの任意のインスタンスからInnerを受け入れることを推測しています。

val o = new Outer(1) 
:type o.Inner 
o.Inner.type 

だから私たちはこのような何かをできるようにするために期待するかもしれない:

class Outer(i : Int) { 
    object Inner { 
    def getI : Int = i 
    } 
    def foo(x : Outer#Inner.type) = x.getI 
} 

これを、しかし、コンパイルに失敗した私たちは、そのような事の種類を確認することができます。なぜ私は分からない。レスキューにエイリアスを入力してください!

class Outer(i : Int) { 
    type Inner = Inner.type 
    object Inner { 
    def getI : Int = i 
    } 
    def foo(x : Outer#Inner) = x.getI 
} 

val a = new Outer(1) 
val b = new Outer(2) 
a.foo(b.Inner) //returns 2 

私はそれはそれは、フォームA#B.typeの何かを読み取ることができないのですパーサだけの制限です推測しています。あなたはバグリクエストを提出する可能性があります。

+0

'type Inner = Inner.type'は' type Inner = this.Inner.type'と同じですか?またはそれらの2つの異なるタイプを参照するでしょうか? –

+1

うん、彼らは同じことを指している。 – Submonoid

0

各Scala objectにはそれぞれ独自の型があり、その型の値は1つだけです。オブジェクト自体です。したがって、Scala objectのタイプは、タイプUnitよりも役に立ちません。

たとえば、あなたがobject Aを持っているとA.typeパラメータを受け取るメソッドまたは関数を宣言言う:

def foo(arg: A.type) = {} 

常にタイプA.typeの1つの値が存在しますので、我々は代わりに参照することにより、何ら一般性を失いませんそれはメソッドfooの中に直接あります。

あなた自身がこれをやりたいと思っ見つけた場合、それはあなたが本当に抽象以上にしたいことは、オブジェクトの形質または基底クラスであることがより可能性があります:

trait Useful { def usefulness: Int } 
object A extends Useful { override val usefulness = 42 } 
class Foo { 
    def foo(arg: Useful) = arg.usefulness 
} 
関連する問題