2011-09-16 4 views
2

私は、単一の抽象メソッドを持つTokenizerクラスを持っていると想像してください。Scalaで主なメソッドを持つ多くの実装を持つクラスを拡張する

trait Tokenizer { 
    def tokenize(sentence: String): List[String] 
} 

実装を提供する多くのトークナイザを実装します。私はこれらのTokenizerのそれぞれが主な方法を持っていることを望みます。私が最初に考えたのは、このようなコードを書くことだった:

abstract class TokenizerMain(tokenizer: Tokenizer) { 
    def main(args: Array[String]) = println(tokenizer.tokenize(args(0)).mkString(" ")) 
} 

class TokenizerOne(val model: String = "foo") extends Tokenizer { 
    def tokenize(sentence: String) = List("asdf") 
} 

object TokenizerOne extends TokenizerMain(new TokenizerOne) { 
} 

しかし、私はエラーが「パラメータは名前による宣言されていない限り、スーパーコンストラクタは自己参照を渡すことはできません」を取得します。 object TokenizerOneobject TokenizerOneMainに改名できますが、classと同じ名前にしておきたいと思います。これを行うより良い方法はありますか?

UPDATE:この問題は、TokenizerOneの暗黙のコンストラクタパラメータmodelが原因であるようです。

答えて

7

はここでバイトコードが起こっているのかを説明できます

class Foo(t: Any) 
class Bar(x: String = "bar") 
object Bar extends Foo(new Bar()) 
    //     ^
    // Error, super constructor cannot be passed a self reference unless 
    // parameter is declared by-name 

、同じエラーを与える削減のコードサンプルです。 REPL、

scala> class Foo(t: Any) 

scala> class Bar(x: String = "bar") 

scala> :javap -v Bar 

Compiled from "<console>" 
public class Bar extends java.lang.Object implements scala.ScalaObject 
... 
{ 
public Bar(java.lang.String); 
... 

から私たちは、クラスBarStringパラメータを取るだけで、単一のコンストラクタを持っていることがわかります。しかし、Barにはデフォルト値x = "bar"を使用するコンストラクタもありますが、それはどこから来ますか?

scala> :javap -v Bar$ 
... 
public java.lang.String init$default$1(); 
    Code: 
    Stack=1, Locals=1, Args_size=1 
    0: ldC#16; //String bar 
    2: areturn 
    LineNumberTable: 
    line 7: 0 

ああは、そのクラスはBar$に属しコンパニオンオブジェクト、(唯一のScalaコンパイラがそのことについて知っていることになっている)で定義されています。

は、だから何が起こっているように見えることはextends Foo(new Bar())にあなたがBarのスーパークラスの初期化時にオブジェクトBarのメソッドにアクセスしようとしている(対象Barの前で実際に構築される)ということです。

これはScalaコンパイラのバグではない場合、混乱しているエラーメッセージです!私はどちらを言うことができません。私は問題SI-5000をバグトラッカーに提出しました。

回避策として、デフォルト値:object Bar extends Foo(new Bar("bar"))を避けることができます。

+0

私は2.9.1を使用しています。 TokenizerOneクラスの暗黙のコンストラクタ引数を忘れてしまった - 私の謝罪。このコンストラクタ引数を追加すると、問題が発生します。 – schmmd

関連する問題