从Java中的基类访问子类字段

时间:2010-12-22 18:20:39

标签: java oop class inheritance subclass

我有一个名为 Geometry 的基类,其中存在一个子类 Sphere

public class Geometry 
{
 String shape_name;
 String material;

 public Geometry()
 {
     System.out.println("New geometric object created.");
 }
}

和一个子类:

public class Sphere extends Geometry
{
 Vector3d center;
 double radius;

 public Sphere(Vector3d coords, double radius, String sphere_name, String material)
 {
  this.center = coords;
  this.radius = radius;
  super.shape_name = sphere_name;
  super.material = material;
 }
}

我有一个包含所有 Geometry 对象的ArrayList,我想迭代它以检查是否正确读取了文本文件中的数据。到目前为止,这是我的迭代器方法:

public static void check()
 {
  Iterator<Geometry> e = objects.iterator();
  while (e.hasNext())
  {
   Geometry g = (Geometry) e.next();
   if (g instanceof Sphere)
   {
    System.out.println(g.shape_name);
    System.out.println(g.material);
   }
  }
 }

如何访问和打印 Sphere的半径和中心字段? 在此先感谢:)

4 个答案:

答案 0 :(得分:11)

如果要访问子类的属性,则必须转换为子类。

if (g instanceof Sphere)
{
    Sphere s = (Sphere) g;
    System.out.println(s.radius);
    ....
}

这不是最常用的做事方式:一旦你有更多的Geometry子类,你将需要开始转换到每个类型,这很快就会变得很乱。如果要打印对象的属性,则应在Geometry对象上使用名为print()的方法或沿着这些线的某些方法,这将打印对象中的每个属性。像这样:


class Geometry {
   ...
   public void print() {
      System.out.println(shape_name);
      System.out.println(material);
   }
}

class Shape extends Geometry {
   ...
   public void print() {
      System.out.println(radius);
      System.out.println(center);
      super.print();
   }
}

这样,您不需要进行转换,只需在while循环中调用g.print()即可。

答案 1 :(得分:1)

您必须cast(具体而言,downcast):

((Sphere) g).radius

答案 2 :(得分:1)

我同意rwhat,但是不是实现你自己的print()函数,它可能会让你受益(并且更加面向对象)以通过覆盖toString()函数来避免向下转换。

public class Geometry 
{
 String shape_name;
 String material;

 public Geometry()
 {
     System.out.println("New geometric object created.");
 }

 public String toString() {
      StringBuilder result = new StringBuilder();
      result.append("Shape name: " + shape_name + "\t");
      result.append("Material: " + material + "\t");
      return result.toString();
 }
 public static void check (Geometry[] gList) {
     for (Geometry g: gList) {
         System.out.println(g.toString());
     }
 }

注意check()并不关心g是球体还是立方体。这有助于最大限度地减少对instanceof的调用。 在球体内...

public class Sphere extends Geometry
 {
  Vector3d center;
  double radius;

  public Sphere(Vector3d coords, double radius, String sphere_name, String material)
  {
   this.center = coords;
   this.radius = radius;
   shape_name = sphere_name;
   super.material = material;
  }
  public String toString() {
      StringBuilder result = new StringBuilder();
      result.append("Radius: " + radius + "\t");
      result.append("Center: " + center.toString() + "\t");
      result.append(super.toString());
      return result.toString();
  }
 }

任何新形状(例如Cone)都可以通过使用toString()函数获益,但缺少它只会打印出Geometry的版本。

答案 3 :(得分:0)

使用instanceof和Cast到所需的子类。您可能希望将这些字段设为公共字段,也可以将私有字段的标准惯用语设置为getter和setter。