2012-03-25 10 views
7

私はScalaを学習しようとしていますので、データ構造を実装することに決めました。私はスタックを始めました。私は次のStackクラスを作成しました。JavaでScala作成クラスを初期化しようとしています

class Stack[A : Manifest]() { 

    var length:Int = -1 
    var data = new Array[A](100) 

    /** 
    * Returns the size of the Stack. 
    * @return the size of the stack 
    */ 
def size = {length} 

    /** 
    * Returns the top element of the Stack without 
    * removing it. 
    * @return Stacks top element (not removed) 
    */ 
    def peek[A] = {data(length)} 

    /** 
    * Informs the developer if the Stack is empty. 
    * @return returns true if it is empty else false. 
    */ 
    def isEmpty = {if(length==0)true else false} 

    /** 
    * Pushes the specified element onto the Stack. 
    * @param The element to be pushed onto the Stack 
    */ 
    def push(i: A){ 
    if(length+1 == data.size) reSize 
    length+=1 
    data(length) = i; 
    } 

    /** 
    * Pops the top element off of the Stack. 
    * @return the pop'd element. 
    */ 
    def pop[A] = { 
    length-=1 
    data(length) 
    } 

    /** 
    * Increases the size of the Stack by 100 indexes. 
    */ 
    private def reSize{ 
    val oldData = data; 
    data = new Array[A](length+101) 
    for(i<-0 until length)data(i)=oldData(i) 
    } 
} 

私はその後、ただし、次の

Stack<Integer> stack = new Stack<Integer>(); 

を使用して、私のJavaクラスでこのクラスを初期化しようとすると、私はコンストラクタが存在しないことを、私は一致する引数を追加する必要があることを告げていますマニフェスト。なぜこれが起こり、どのように修正できますか?

答えて

18

Alexeyが正しい説明をくれましたが、コードでマニフェストを作成することは間違いありません(Javaで簡単に作成できるjava.lang.Classオブジェクトが必要です)。

まず、スタックのコンパニオンオブジェクトにJavaフレンドリーファクトリメソッドを追加する必要があります

object Stack { 
    def ofType[T](klass: java.lang.Class[T]) = { 
    val manifest = new Manifest[T] { 
     def erasure = klass 
    } 
    new Stack()(manifest) 
    } 
} 

この方法は、(Javaクラスからの)適切なマニフェストを生成し、それが明示的へ渡しますStackコンストラクタ。あなたはその後、痛みなし、Javaからそれを使用することができます:

Stack<String> stack = Stack.ofType(String.class); 
stack.push("Hello"); 
stack.push("World"); 

System.out.println(stack.size()); 
System.out.println(stack.peek()); 
9

これは、[A : Manifest]のようなコンテキストバインドが、暗黙的なコンストラクタ引数の短縮形にすぎないために発生します。したがって、あなたのクラスはclass Stack[A]()(implicit m: Manifest[A]) {と「本当に」宣言されています。したがって、Manifestを作成する唯一の方法はコンパイラの魔法です(私が知る限り)。それはJavaからはできず、Stackを構築することはできません。

マニフェストを避けるようにデザインを変更するか、ScalaコードでStackのインスタンスを作成し、Javaからのみ使用することができます。

+1

+1、コンパイラの魔法なし 'Manifest'を作成することが可能です。私の答えを見てください。 – paradigmatic

2

はパラダイム答えにフォローアップ、あなたも、あなたのクラスのコンストラクタを作成することができます。そして、Javaから呼び出すことができます

class Stack[A](implicit m: Manifest[A]) { 

def this(clazz : Class[A]) { 
    this()(new Manifest[A] { 
    def erasure = clazz 
    }) 
} 

Stack<Integer> s = new Stack<Integer>(Integer.class); 
s.push(1); 
System.out.println(s.peek()); 

しかし、問題は、文字列のスタックのスタックを持つような一般的なタイプとなります。このためには、このスレッドになります。説明のためのhttp://www.scala-lang.org/node/7267

関連する問題