2011-07-06 11 views
6

org.junit.Assert.assertEqualsメソッドを静的にインポートするJunit4テストケースがあります。私は等号を実装していないいくつかの複雑な内部クラスをアサートするためのユーティリティメソッドを作成しました。このクラスでは クラスにインポートされたメソッドと同じ名前のメソッドがある場合、import staticは機能しません。

import static org.junit.Assert.assertEquals; 

は(とも苦労それを実装してい)。

private void assertEquals(MyObj o1, MyObj o2) 
{ 
    assertEquals(o1.getSomething(), o2.getSomething()); 
    assertEquals(o1.getSomethingElse(), o2.getSomethingElse()); 
    ... 
} 

は、私は私が輸入していますassertEquals方法(複数可)「のオーバーロード」していたかのようコードが動作するように期待されるが、静的にインポートする方法を隠してそれは私の民間非静的メソッドのように見えます。私もpublicstatic(すべての順列)に私のメソッドを回してみましたが、成功なし - 私はそれを名前を変更する必要がありました。

このように動作する理由は何ですか?私はドキュメントでこの動作への参照を見つけることができませんでした。

+1

内部メソッドのシグネチャ(または名前)を変更するのを止めたいのは何ですか? – spot35

+1

@DomSelvon、署名の変更は役に立ちません。メソッド名について - 何も私を止めていません - 質問は純粋に知識のためです(既に名前が変更されています) – RonK

答えて

3

ご覧いただいた内容はShadowingです。 javaの2つの型が同じシンプルな名前を持つ場合、そのうちの1つが他のものをシャドウします。シャドータイプはシンプルな名前では使用できません。

最も一般的なタイプのシャドーイングは、フィールドを非表示にするパラメータです。

静的インポート・オン・デマンド宣言が影にする他の宣言を起こしたことがない:通常、今度はrelevant documentationを読んでみましょうsetMyInt(int myInt) {this.myInt = myInt; }

見えるようにセッターのコードにつながります。

これはオンデマンドの静的インポートが常に最後になることを示しています。したがって、オンデマンドでの宣言と同じ簡単な名前を持つタイプは常に静的インポートをシャドウ(非表示)します。

+0

私はあなたの説明とスペックの両方を読んだ後でそれを告白しなくてはなりませんが、特定の署名を持つ1つの方法が別のものをなぜシャドウするのかまだ分かりません。 – RonK

+0

この場合に期待していますか?どちらのメソッドも同じシンプルな名前を持っているので、どのメソッドを呼び出そうとしたのかを魔法のように推測する方法はありません(私的なものと静的なものをインポートしたもの)。 – Dorus

+0

それでも、なぜあなたが他の方法よりも1つの方法を好む理由が得られないということを意味しましたか?それは、スペックでルールを注意深く読んで適用するだけです。全体的に、それはローカルなものを好んで、次にクラスを選び、次に継承し、次にインポートし、次にオンデマンドでインポートすると言うことができます。 – Dorus

1

オーバーロードと上書きは継承ツリーで機能します。しかし、静的インポートは継承を構築しません。

自分のassertEqualsメソッドでjunitのassertEqualsを使用する場合は、classNameで修飾する必要があります。 Assert.assertEquals。

org.junit.Assertの非静的インポートを使用してください。

+0

これはカスタムメソッドの名前を変更することなく最良の答えと思われます。 – Joseph

0

method hidingに遭遇しました。ローカルメソッドが存在すると、別のクラス(多くの場合、スーパークラス)のものが隠されます。

私は静的にメソッドをインポートすることは、構文的に可能ではあるが、何とか「間違っている」と常に感じていました。

スタイルとして、私はクラスをインポートし、TheirClass.method()を自分のコードに使用することを好みます。そうすることで、メソッドがローカルメソッドではなく、良いコードの特徴の1つが明快であることが明らかになります。

import org.junit.Assertをお勧めします。Assert.assertEquals(...)を使用してください。

+0

このスタイルは、メソッドがどこから来ているかを明確にします。しかし、重要な問題は「それは何ですか?」ということです。その点で何かを明らかにせずに文字数をほぼ倍増させました。 –

+0

Dorusと同様に、これは[_shadowing_](http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4.1)であり、_hiding_ではありません。 'Assert.assertEquals'メソッドは継承されません。 –

0

これは意味があります。 javacがあなたの望むことをしているとすれば、今日はassertEquals(MyObj, MyObj)メソッドを選択します。明日org.junit.Assertに独自のassertEquals(MyObj, MyObj)メソッドが追加されたらどうなりますか?呼び出しの意味assertEquals(mo1,mo2)あなたがそれを知らずに劇的に変更されました。

質問の意味はassertEqualsです。 Javacはこれがメソッド名(org.junit.Assert)であることを決定する必要があります。それ以降は、メソッドオーバーロードの解決を行うことができます。のすべてのメソッドをassertEqualsという名前で調べ、最も適切なメソッドを選択します。

javaは複数のクラスからメソッドオーバーロードを処理できると考えられますが、最初の段落に示すように、開発者は彼が呼び出しているメソッドの開発者に大きな不確実性をもたらします。これらのクラスは無関係であるため、メソッドのセマンティクスは大きく異なる可能性があります。

コンパイル時に、メソッドがどのクラスに属しているかを疑うことなく開発することができますが、明示的にメソッドがオーバーロードされ、呼び出されるターゲットメソッドが変更される可能性があります。 しかし、これは同じクラスで行われるため、責任を負うことができます。たとえば、org.junit.Assertが新しいassertEquals(MyObj, MyObj)メソッドを追加することを決定した場合、以前の呼び出しであるassertEquals(Object,Object)が新しいメソッドに再ルーティングされるようになり、呼び出しサイトを壊すセマンティクスの変更がないことを確認する必要があります。

関連する問題