私はJavaに不慣れで、作成したクラスのサブクラスを形成するのに問題があります。私が作成したクラスは、_Vector2D
_と呼ばれ、_Vector2D
_オブジェクトを引数として取り、_Vector2D
_オブジェクトを返すadd(Vector2D addend)
などのメソッドを含みます。このメソッドは特に、2つのベクトルを加算して合計を返すように設計されています。
次に、_Position2D
_というサブクラスのコーディングを開始しました。これは、追加の関数を除き、_Vector2D
_クラスのすべての機能を持ち、内部で_Vector2D
_を使用する予定です。引数、戻り値の型など、既存のクラスを_Position2D
_で置き換えて、add(Position2D addend)
関数が2つの_Position2D
_ベクトルを加算し、合計をaとして返すようにします。 _Position2D
_。
_Position2D
_が_Vector2D
_から継承されると、このような関数は_Vector2D
_オブジェクトに関して機能し続け、_Position2D
_オブジェクトが渡されるとすぐにエラーを吐き出すという問題が発生しますそれを通して。
_Vector2D
_クラスの関連コードは次のとおりです。
_public class Vector2D{
//Field Variables
private double x; //The vector's x-coordinate
private double y; //The vector's y-coordinate
//Constructors
public Vector2D(){
//Constructs empty vector.
setX(0);
setY(0);
}
//Methods
public void setX(double newX){
//This method is not problematic when inherited for the subclass.
x = newX;
}
public void setY(double newY){
//This method is not problematic too.
y = newY;
}
public Vector2D add(Vector2D addend){
//Adds two vectors and returns the sum.
//This method, however, does pose a problem.
Vector2D sum = new Vector2D();
sum.x = x + addend.x;
sum.y = y + addend.y;
return sum;
}
}
_
_Position2D
_のadd(Position2D addend)
のコードが何であるかについて私が現在考えることができる唯一の回避策は:
_public Position2D add(Position2D addend){
//Adds two position vectors and returns the sum.
Position2D sum = new Position2D();
sum.x = x + addend.x;
sum.y = y + addend.y;
return sum;
}
_
つまり、_Vector2D
_からメソッドを繰り返し、手動で変更します。もちろん、これは効率的ではなく、時間を浪費します。特に、同様のメソッドに対して同じことを行う必要がある場合はいつでも、さらにサブクラスを作成するつもりの場合は常にそうです。 _Velocity2D
_。したがって、これを行うためのよりクリーンで効率的な方法を探しています。
継承は「ある」種類の関係を定義することを忘れないでください。コード
class Position2D extends Vector2D
すべてのPosition2DはVector2Dですが、その逆ではないことをコンパイラーに伝えます。
上記の宣言をすでに行っていると想定して、次の例を確認してください。
// obviously okay, type of instance matches reference type
Vector2D vecVecRef = new Vector2D();
Position2D posPosRef = new Position2D();
// this is okay because a Position2D is a Vector2D
Vector2D posVecRef = new Position2D();
// The compiler will not automatically convert a Vector2D to a Position2D
Position2D vecPosRef = new Vector2D(); //Compiler error!
Position2D変数がVector2Dオブジェクトを参照することはありません。型キャストを試みると、コンパイラーは「問題ありません...私はあなたを信頼しています」と言いますが、JVMは、Vector2DをPosition2Dに割り当てようとしていることを実際に検出すると怒ります。実行時にClassCastException
が発生します。
// compiles fine but raises ClassCastException in runtime
Position2D vecPosRef = (Position2D) new Vector2D();
これは、サブクラスをスーパークラスにキャストできるのはクラスのみであり、その逆はできないためです。したがって、基本的に、Vector2DをPosition2Dにキャストすることはできず、キャストせずに割り当てることもできません。
この問題の最も簡単な解決策は、特定のVector2DオブジェクトからPosition2Dオブジェクトを作成するコンストラクターをサブクラスで定義することです。
class Position2D extends Vector2D {
Position2D() {
// default stuff
}
Position2D(Vector2D v) {
// you currently don't have the getX and getY methods
// so define them in your superclass
setX(v.getX());
setY(v.getY());
}
}
その1つのシンプルで便利なコンストラクターを使用すると、次のようなコードを使用できます。
public class Inheritance {
public static void main(String[] args) {
Position2D pos1 = new Position2D();
Position2D pos2 = new Position2D();
pos1.setX(3);
pos1.setY(4);
pos2.setX(5);
pos2.setY(6);
Position2D pos3 = new Position2D(pos1.add(pos2)); // using constructor
System.out.println(pos3.getX()); // this prints 8.0
}
}
ご覧のとおり、この方法は、すべてのサブクラスメソッドを書き換えるよりもはるかに拡張可能です。
依存性逆転原理 と factory methodパターン 。
戻り値の型は、_Vector2D
_と_Position2D
_の両方のスーパータイプである必要があります。
それを_IVector2D
_(インターフェース)と呼びましょう。
解決策は次のとおりです。
_public interface IVector2D {
public void setX(double newX);
public void setY(double newY);
public double getX();
public double getY();
public IVector2D add(IVector2D addend);
public IVector2D getInstance(); // this helps decouple the instantiation
}
_
その後
_public class Vector2D implements IVector2D {
private double x; //The vector's x-coordinate
private double y; //The vector's y-coordinate
public Vector2D(){ setX(0); setY(0); }
public IVector2D getInstance(){ return new Vector2D(); }
@Override
public void setX(double newX) { x = newX; }
@Override
public void setY(double newY) { y = newY; }
@Override
public double getX() { return this.x; }
@Override
public double getY() { return this.y; }
@Override
public IVector2D add(IVector2D addend) {
IVector2D sum = getInstance();
sum.setX(this.getX()+addend.getX());
sum.setY(this.getX()+addend.getY());
return sum;
}
}
_
拡張するときは、getInstance()
をオーバーライドしてコンストラクタを実装します。
_public class Position2D extends Vector2D {
public Position2D(){ super(); }
@Override
public IVector2D getInstance(){ return new Position2D(); }
}
_
getInstance()
とadd()
をオーバーライドしているため、実際には_Position2D
_型の参照内で_Ivector2D
_型のオブジェクトを返していることに注意してください。 _Position2D
_のgetInstance()
を呼び出します。その抽象化により、add()
メソッドがシームレスに機能できるようになりました。
テストプログラムは次のようになります。
_public static void main(String[] args) {
IVector2D a = new Position2D();
IVector2D b = new Position2D();
a.setX(1.2d);
a.setY(2.3d);
b.setX(0.33d);
b.setY(9.0d);
IVector2D c = a.add(b);
System.out.println(c.getX());
}
_
出力:
_1.53
_