0

次のクラスを仮定します。

interface Thing {
  void doSomething();
}

public class Test {
  public void doWork() {
    //Do smart things here
    ...
    doSomethingToThing(index);
    // calls to doSomethingToThing might happen in various places across the class.
  }

  private Thing getThing(int index) {
    //find the correct thing
    ...
    return new ThingImpl();
  }

  private void doSomethingToThing(int index) {
    getThing(index).doSomething();
  }      
}

Intelli-J は、DoSomethingToThing が関数の結果を使用しており、おそらくフィールド、パラメーター、またはオブジェクト自体のメソッドしか呼び出せないため、デメテルの法則に違反していると言っています。

私は本当にこのようなことをしなければなりませんか:

public class Test {
  //Previous methods
  ...

  private void doSomething(Thing thing) {
    thing.doSomething();
  }

  private void doSomethingToThing(int index) {
    doSomething(getThing(index));
  }
}

私はそれが面倒だと思います。デメテルの法則は、あるクラスが別のクラスの内部を知らないがgetThing()、同じクラスであるようにするためのものだと思います!

これは本当にデメテルの法則に違反していますか?これは本当にデザインを改善していますか?

ありがとうございました。

4

2 に答える 2

0

IntelliJ がオブジェクトのインスタンス化を正しく検出していません。

ウィキペディア (IDEA のリンク先) では、現在のコンテキストで作成されたオブジェクトを呼び出すことができると説明されています。

それが私がしていることですが、それでも次の警告が表示されgetMajor()ます:

Version version = Loader.readVersion(inputStream); // Instantiates a new Version

if (version.getMajor() != 2)
    throw new IOException("Only major version 2 is supported");

IDEA のインスペクションには、「ライブラリ」メソッドの呼び出しを無視するオプションがあります。私の場合Loader.readVersion() 、ライブラリ メソッドですが、現在のプロジェクト内にあります (プロジェクトは自立している必要があります)。IDEA は、ライブラリ メソッドではないと考えています。

このインスペクションのメカニズムは不適切/不完全/ナイーブであるため (多くの IDEA のインスペクションと同様)、唯一の解決策はそれを無効にして、これらの状況を手動で回避しようとすることです。

于 2016-08-10T10:41:07.793 に答える