web-dev-qa-db-ja.com

オブジェクト内の引数(パラメーター)によってフィールド(インスタンス変数)を渡す-意味がありますか?

これは言語にとらわれない質問だと思います。そうでない場合は修正してください。

クラスがあるとしましょう(コードスニペットは「疑似コード」の一種です)

class Car:
  private steering_wheel
  private engine
  public Car(steering_wheel, engine):
    this.steering_wheel = steering_wheel
    this.engine = engine


  public void service():
     clean_steering_wheel()
     repair_engine()

  private void clean_steering_wheel():
    this.steering_wheel.do_stuff()

  private void repair_engine():
    this.engine.do_stuff()

うまくいきます!しかし、プライベートメソッドを少し変更して、フィールド(つまりsteering_wheelおよびengine)直接ではなく、引数を介して

   class Car:
  private steering_wheel
  private engine
  public Car(steering_wheel, engine):
    this.steering_wheel = steering_wheel
    this.engine = engine


  public void service():
     clean_steering_wheel(this.steering_wheel)
     repair_engine(this.engine)

  private void clean_steering_wheel(steering_wheel):
    steering_wheel.do_stuff()

  private void repair_engine(engine):
    engine.do_stuff()

すべてのパラメーター(引数)が参照によって渡されると仮定しましょう。

これらのソリューションの長所と短所は何ですか?どちらがより良い実践と考えられていますか?あなたはどちらを好みますか?

2
Filip Bartuzi

特定の状況に対する判断の呼びかけに聞こえますが、いくつかの考慮事項が頭に浮かびます。メソッドがプライベートであり、理由が何もない場合toパラメータを渡す場合、あまり複雑でないこと以外に理由がない場合は、おそらくそれを避けます。追加のパラメーターが必要ない場合にスタックに渡す理由がないため、これを回避するパフォーマンス上の理由があると主張することもできます。

保護されたメンバーと一緒にパラメーターとしてメンバーを渡すdoメンバーを見つけたことがあります。子クラスが、同様にクリーンアップする必要がある2番目のステアリングホイールを追加するようなことをするとします。その場合、(おそらく)基本クラスのclean_steering_wheelメソッドを再利用して、別のステアリングホイールメンバーを渡すことができます。

2
Steve Williams

メソッドを呼び出さずに関数/静的メソッドを使用する場合は、フィールドを明示的なパラメーターとして渡す方が優れています。関数で使用できるデータが少ないほど、すべての依存関係が明示的であるほど、そのコードについて推論しやすくなります。そのため、関数clean_steering_wheel(steering_wheel)は、実際にエンジンを使ってユーザーを驚かせることはありません。

ただし、(プライベート)メソッドは、暗黙のengineパラメーターを介してthisおよびsteering_wheelへの参照をすでに受け取ります。明示的なsteering_wheelパラメータに加えてthisパラメータがある場合は、データを複製しているため、矛盾が発生する可能性があります。特に、thissteering_wheelを使用しなかった理由を知りたいのですが、別のCarsteering_wheelを使用していますか? Carに属していないsteering_wheelについて

これを考慮して、clean_steering_wheelを次のように定義することで混乱が少なくなります。

private void clean_steering_wheel():
  this.steering_wheel.do_stuff()

ただし、無料の関数を使用することをお勧めします。

void function clean_steering_wheel(steering_wheel):
  steering_wheel.do_stuff()

void function repair_engine(engine):
  engine.do_stuff()

class Car:
  ...

  public void service():
    clean_steering_wheel(this.steering_wheel)
    repair_engine(this.engine)

、または静的メソッド:

class Car:
  ...

  public void service():
    clean_steering_wheel(this.steering_wheel)
    repair_engine(this.engine)

  private static void clean_steering_wheel(steering_wheel):
    steering_wheel.do_stuff()

  private static void repair_engine(engine):
    engine.do_stuff()

どの正確なアプローチを使用するかは、かなり言語固有であり、テスト容易性にも影響を与えます。例えば。 C++では、匿名の名前空間で無料の関数を使用すると、カプセル化は最適になりますが、テスト性が大幅に低下します。プライベート静的メンバー関数は、フレンドクラスでテストできるため、優れている場合があります。 Javaでは、無料の関数は使用できませんが、必須は「静的メソッド」を使用するため、説明は不要です。

1
amon