11/24 簡単なグラフィクス(1)


質問と回答

Q.
11/17 の講義用資料のメソッドのオーバーライド の所で 「親クラスの型の変数に子クラスの型のオブジェクトを代入することはできる. その場合 も,動的メソッドの呼び出しをした場合は子クラスでオーバーライド されたメソッドの プログラムが実行される. 子クラスの型の変数に親クラスのオブジェクトを代入する際には,キャスト演 算子を使 って,「(子クラス名)式」のように使う.ただし,子クラスで定義さ れていないデータ フィールドをアクセスしようとしたり,子クラスで定義され ていないメソッドを呼び出 そうとすると,実行時にエラーが発生する. 」 の部分の意味が良くわかりませんでした。まず第一に「親クラスの型の変数に子クラスの型のオブジェクトを代入する」の意味からわかりません。例かなにかで説明しては頂けないでしょうか。
A.
ちょっと難しかったようですね.講義用資料で言うと,親クラスをPoint2D,子クラスをPoint3Dとした時に,
 Point2D p1; // 親クラスの変数
 p1 = new Point3D(1.0,1.0,1.0); // 子クラス(Point3D)のオブジェクトを代入
とできるという意味です.その後で,動的メソッド length を呼び出すと
 double len=p1.length(); // 変数の型である Point2Dで定義されたlengthではなく,
                         // インスタンスの型である Point3Dで定義された length
                         // が呼ばれる.
となります.

後半は,

 Point3D p2=(Point3D)new Point2D(1.0,1.0);
とすることは可能だけれども,メソッド呼び出しや変数アクセスなどをする と実行時にエラーが出るということを言っています.

前回の課題について

課題問題

Point2Dクラスのサブクラスとして, length(), distance3d(Point3DName), distance2d(Point2D)というメソッド, x, y, z, nameというインスタンス変数を持つPoint3DNameというサブクラスを作って, 次のプログラムを完成させなさい.

class Point2D {
  public double x,y;
  public Point2D(double xx,double yy){
    x=xx; y=yy;
  }
  public double length(){
    return Math.sqrt(x*x+y*y);
  }
  public double distance2d(Point2D point2){
    double dx=(x-point2.x),dy=(y-point2.y);
    return Math.sqrt(dx*dx+dy*dy);
  }
}

class Point3DName extends Point2D {
// この部分を埋めなさい.
}

class ObjectTest8 {
  public static void main(String[] args){
    Point3DName p1,p2,p3;
    p1=new Point3DName(0.0,0.0,1.0,"Point1");
    p2=new Point3DName(1.0,1.0,1.0,"Point2");
    p3=new Point3DName(0.0,1.0,0.0,"Point3");
    System.out.println("length of "+p1.name+" = "+p1.length());
    System.out.println("length of "+p2.name+" = "+p2.length());
    System.out.println("length of "+p3.name+" = "+p3.length());
    System.out.println("2D distance between "+p1.name+" and " +p2.name+" = "+p1.distance2d(p2));
    System.out.println("2D distance between "+p2.name+" and " +p3.name+" = "+p2.distance2d(p3));
    System.out.println("2D distance between "+p3.name+" and " +p1.name+" = "+p3.distance2d(p1));
    System.out.println("3D distance between "+p1.name+" and " +p2.name+" = "+p1.distance3d(p2));
    System.out.println("3D distance between "+p2.name+" and " +p3.name+" = "+p2.distance3d(p3));
    System.out.println("3D distance between "+p3.name+" and " +p1.name+" = "+p3.distance3d(p1));
  }
}

解答例

class Point3DName extends Point2D {
   // x, yの宣言は不要
   // 親クラスにないインスタンス変数zの宣言
  public double z; 
   // 親クラスにないインスタンス変数nameの宣言
  public String name;
   // コンストラクタを定義する必要がある.
  public Point3DName(double xx,double yy,double zz,String nn){
     // x=xx; y=yy; でも 可
    super(xx,yy);
    z=zz;
    name=nn;
  }
  public double length(){
     // 親クラスの length は z を見ていないので使えない.
    return Math.sqrt(x*x+y*y+z*z);
  }
   // 親クラスにないメソッド distance3d の宣言
  public double distance3d(Point3DName p){
    double dx=(x-p.x),dy=(y-p.y),dz=(z-p.z);
    return Math.sqrt(dx*dx+dy*dy+dz*dz);
  }
   // distance2dは親クラスの定義をそのまま使えるので宣言は不要
}

今回は課題が3つある.課題をこなしたら, lectures.g99.cp1-ktanaka-W-Wed-5 のニュースグループに投稿すること.
次に進む