web-dev-qa-db-ja.com

派生クラスで継承されたメソッドを無効にする

Java派生クラスで、基本クラスから継承されるメソッドやフィールドを「無効にする」方法はありますか?

たとえば、rotate()メソッドを持つShape基本クラスがあるとします。 Shapeクラスから派生したさまざまなタイプもあります:SquareCircleUpwardArrowなど。

Shapeにはrotate()メソッドがあります。しかし、rotate()Circleのユーザーが利用できないようにしたいのです。無意味だからです。UpwardArrowのユーザーは、UpwardArrow回転できるようにします。

それは可能ではないと思います。ただし、仕様からrotate()メソッドを削除してShapeクラスをさらに洗練し、代わりに---と呼ばれるShapeの別のsubclassを定義することができますRotatableShapeおよびCircle derive from Shapeおよびその他すべてのRotatableクラス from RotatableShapeを許可します。

例えば:

public class Shape{
 //all the generic methods except rotate()
}

public class RotatableShape extends Shape{

 public void rotate(){
    //Some Code here...
 }
}

public class Circle extends Shape{
 //Your implementation specific to Circle
}

public class Rectangle extends RotatableShape{
 //Your implementation specific to Rectangle
}
39
Chandu

次のように、この操作を無効にしたいクラスの特定のメソッド「rotate()」をオーバーライドできます

public void rotate() {
    throw new UnsupportedOperationException();
}
17
Wavyx

子クラスのメソッドを無効にする必要がある場合、クラス階層が不適切です。サブクラスは、スーパークラスのメソッドをスムーズに使用できる必要があります。これは「リスコフ代替原則」と呼ばれます( https://en.wikipedia.org/wiki/Liskov_substitution_principle )。詳細については、このスレッドをご覧ください https://softwareengineering.stackexchange.com/questions/219543/should-a-class-know-about-its-subclasses

Chanduの提案に従ってください。 Shapeにrotate()を入れないでください。代わりに、RotatableShapeと呼ばれるShapeのサブクラスを作成し、rotate()をそこに配置します。次に、CircleはShapeから継承でき、RectangleはRotatableShapeから継承できます。

5
Nick Crews

番号。

  • Circleクラス(またはそのクラスによってのみ実装されるインターフェース)のみでメソッドをプルダウンできます
  • 空の実装、またはそれをサポートしないクラスでUnsupportedOperationExceptionをスローする実装を提供できます。
4
Bozho

「子」クラスで同じ関数を宣言すると、基本クラスで宣言されているデフォルトの関数が上書きされます。したがって、子クラスで、何もしないrotate()という関数を作成します。これにより、デフォルトの動作が上書きされます

3
rsplak

サークルに空の(何もしない)メソッドを使用できますか?矢印については、オブジェクト階層を再考します

3
Riccardo Cossu

これに対処する1つの方法は、(たとえば)boolean isRotatable()と呼ばれる2番目のメソッドを定義し、これを使用して、ユーザーが回転コントロールを使用できるかどうかを判断することです。

別のオプションは、Rotatableインターフェイスを導入し、_shape instanceof Rotatable_を使用して決定することです。 (ただし、isRotatable()アプローチの方が柔軟性があると思います。)

どちらの場合でも、次のように回転してはならないクラスにrotate()メソッドを実装できます。

_public void rotate() {
    throw new UnsupportedOperationException("rotate");
}
_

Java言語は、サブクラスのメソッドを「削除」または「無効化」する方法を提供しません。これは、代入可能性の原則に違反し、多態性を破壊します。サブクラスは、可視メンバーを親クラスAPI。

2
Stephen C

提案した方法でメソッドを無効にできるとは思いません。

あなたの例では、形状を取るメソッドがあるとしましょう

public void handleShape(Shape s){
  s.rotate();
}

次に、このメソッドにCircleを渡します

handleShape(new Circle());

どうなりますか?基本的に、Javaの型システムの根本的な変更を求めています。

CircleがShapeであり、回転させるべきではない場合、おそらくShapeの設計が不十分であり、回転メソッドを持つべきではないことを意味します。 RotatableShapeなどの階層の別のクラスに回転を追加したり、場合によってはインターフェースRotatableを使用したりできます。

1
richs

したがって、ここには2つの可能性があります。 1つは、回転できるオブジェクトがありますが、プロセスに変化がないことです。もう1つは、その方向によって定義されるオブジェクトがあることです。それぞれを個別に、独自の方法で処理する必要があります。

だから サークル、システムに変更がないため、回転関数のスタブがあります。気に入らないでください。これを書くためにポイントグループのクイズを延期しています。
ために 上向き矢印、一方通行で間違った方向に運転したくないので例外をスローしますが、これはとにかく一定でなければなりません。

私の場合、クォータニオンを定義するクラスから操作を継承することにより、3次元空間でポイントを定義しています。 3次元ポイントは、クォータニオンの3つの虚数座標のみを使用し、クォータニオンが実際のコンポーネントに対してゼロ以外の値を持っている場合、3次元座標を介してクォータニオンから継承されたレンダリングアルゴリズムの重要な操作を台無しにします。

あまりにも哲学的であるとは申し訳ありませんが、この質問は、CSでこれをどのように処理すべきかについて有効なポイントを提起します。スティーブンが指摘しているように、子クラスで継承された関数を非表示、無効化、または削除できると、「...代替可能性の原則に違反し、多態性が損なわれます」。

私のケースは、私が想像力を向けているのを除いて、上向きの矢印に該当します。私は派生クラスを切り捨てようとしています。つまり、「孫」クラス(おそらくスピン演算子を継承)は、必ずしも四元数である必要はありません。切り捨てられた派生クラスの型キャストで基本クラスをトリミングすることで、例外のスローに頼らないようにする方がエレガントです。別の方法として、3次元座標を、クォータニオンメンバー変数を持つ個別のクラスとして定義します。欠点は、実装に接着剤が多すぎることです。

次に、3つの平面(ij、jk、ik)の3次元座標の派生クラスに新しいスピン操作を配置し、3d頂点を持つオブジェクトをループおよび各頂点の同一のメンバー関数呼び出しを介して回転できます。 。球の表面を定義するポイントの回転を開始する前に、自分で対称性を追跡することができます。そのため、スタブ関数を使用して、独自の「定数」フラグを実装する必要があります。

1
JustKevin

カスタムアラートダイアログにも同じものが必要でした。ショーの瞬間にのみ利用可能になる引数を渡す必要があったので、show(argument)メソッドを実装しましたが、スーパークラスのためにshow()も機能しました。引数なしでmyDlg.show()を誤って呼び出すことがあり、クラッシュを引き起こす可能性がありました。スーパークラスメソッドがCustomAlertDialogクラスの外部で呼び出されないようにするために、メソッドprivate static void show(){}を追加しました。それでおしまい。

したがって、スーパーメソッドを無効にするには、それをサブクラスでプライベートおよび静的にします。あなたの場合、それは:

 private void rotate(){}
0
Eugene Kartoyev