【问题标题】:How to typecast this class?如何对此类进行类型转换?
【发布时间】:2016-04-27 03:41:43
【问题描述】:

我有一个叫做 BasketBallPlayer 的超类

我有一个名为 ProBasketBallPlayer 的子类

如果我创建一个对象

BasketBallPlayer bp1;
bp1=new BasketBallPlayer("Tim Duncan", "Center", "Spurs", 83, 220, 4, 5, 8);


public class BasketBallPlayer {
    protected String name;
    protected String position;
    protected String team;
    protected int height;
    protected int weight;
    protected int agility;
    protected int speed;
    protected int ballHandling;

    public BasketBallPlayer() {
        this.name = "unknown";
        this.position = "unknown";
        this.team = "unknown";
        this.height = 0;
        this.weight = 0;
        this.agility = 0;
        this.speed = 0;
        this.ballHandling = 0;
    }

    public BasketBallPlayer( String name, String position, String team)
    {
        this.name = name;
        this.position = position;
        this.team = team;
        this.height = 0;
        this.weight = 0;
        this.agility = 0;
        this.speed = 0;
        this.ballHandling = 0;
    }

    public BasketBallPlayer (String name, String position, String team, int height, int weight,
                int agility, int speed, int ballHandling)
    {
        this.name = name;
        this.position = position;
        this.team = team;
        this.height = height;
        this.weight = weight;
        this.agility = agility;
        this.speed = speed;
        this.ballHandling = ballHandling;
    }

如何在不出现 ClassCastException 的情况下将其类型转换为 ProBasketballPlayer

这是 ProBasketballPlayer 的构造函数

public class ProBasketballPlayer extends BasketBallPlayer {
    protected int yearsInLeague;
    protected String role;

    public ProBasketballPlayer()
    {
        super();
        yearsInLeague = 0;
        role = "bench";
    }

    public ProBasketballPlayer( String name, String position, String team )
    {
        super(name, position, team);
        this.name = name;
        this.position = position;
        this.team = team;
        yearsInLeague = 0;
        role = "bench";
    }

    public ProBasketballPlayer(String name, String position, String team, int height, int weight,
            int agility, int speed, int ballHandling, int yearsInLeague, String role)
    {
        super(name, position, team, height, weight, agility, speed, ballHandling);
        this.yearsInLeague = yearsInLeague;
        this.role = role;
    }

【问题讨论】:

  • 您只能将子类转换为其超类,反之则不行。简单来说,法拉利是一种车,但车不是法拉利的一种。我可以创建一个 List 并将梅赛德斯、法拉利和福特汽车添加到列表中,考虑到这些子类中的每一个都有一个超类 Car。
  • 你应该让你的蒂姆邓肯节食。在 83 厘米的高度体重 220 磅听起来并不健康。
  • @RolandIllig 有些东西告诉我它是英寸... XD
  • @4castle:感谢您的解释。 — 所以这个程序应该只由美国人来维护,而不是由欧洲人来维护。因为对他们来说,可能看起来身高(220 厘米)和体重(83 公斤)混在一起,导致球员身材高大但非常瘦。

标签: java class oop object inheritance


【解决方案1】:

你不能。转换不会改变对象的任何内容,它只是告诉编译器它可以将对象解释为在类层次结构中进一步向上的类,但不能向下。一旦您实例化了一个对象,就是这样 - 该对象绝对是您实例化的类的成员,并且不可撤销。它是BasketballPlayer,永远不会是ProBasketballPlayer。如果您想要 Pro,请实例化一个 - 您可以将 Pro 用作普通篮球运动员,但反之则不行。

举个例子:

class Foo
{
    int a;
}
class Bar extends Foo
{
    int b;
}

Foo obj = new Foo();
obj.a = 0; // our obj has an "a" field because it is a Foo.
obj.b = 0; // but no "b" field, because it is not a Bar.

// It therefore makes no sense to do this:
((Bar)obj).b = 0; // because that's the same as trying to do "obj.b"

// in either case, "obj" is not a "Bar", and cannot have a "b" field. "obj" will always be a "Foo", never a "Bar".

//
// If however we make a Bar:
Bar obj2 = new Bar();

// we can access both fields, since Bar has both of them
obj2.a = 0;
obj2.b = 0;

// and, since Bar is a SUPERSET of Foo (all Bar are Foo, not all Foo are Bar), 
// we can even use obj2 as a Foo, and pass it to methods which accept a Foo.

【讨论】:

    【解决方案2】:

    如何在不获取的情况下将其类型转换为 ProBasketballPlayer ClassCastException

    你不能投错方向。想想下面的两个陈述......

    1. ISA BasketballPlayer 还是 ProBasketballPlayer?
    2. 都是 BasketBallPlayers ProBasketBall 球员吗?

    没有。我打篮球,但我不是职业篮球运动员。

    每个Bird 都是Duck

    Bird b = new Bird();
    Duck daffy = (Bird)b;
    daffy.quack(); // Error here, not all birds quack?
    

    【讨论】:

      【解决方案3】:

      您不能将对象强制转换为子类。对象只能从其构造函数的类型“向下”转换。每个Cat 都是Animal,但不是每个Animal 都是Cat。投射只有一种方式。

      可以做的是在ProBasketballPlayer 中创建一个接受BasketBallPlayer 并在相关字段中复制的构造函数。确保初始化 ProBasketballPlayer 可能还有的任何其他字段。

      public ProBasketballPlayer(BasketBallPlayer bbp, int yearsInLeague, String role) {
          super(bbp.getName(), bbp.getPosition(), bbp.getTeam(), bbp.getHeight(), bbp.getWeight(), bbp.getAgility(), bbp.getSpeed(), bbp.getBallHandling());
          this.yearsInLeague = yearsInLeague;
          this.role = role;
      }
      
      public public ProBasketballPlayer(BasketBallPlayer bbp) {
          this(bbp, 0, "bench");
      }
      

      如果ProBasketballPlayerBasketBallPlayer 在同一个包中,那么您可以直接访问字段(例如bbp.name)而不是使用getter。

      【讨论】:

      • 好的,我喜欢这样的声音,但是我如何创建一个构造函数来接受 ProBasketballplayer 内部的类似内容?
      • 更新了我的答案。您必须为BasketBallPlayer 中的所有实例数据创建getter,否则protected 将阻止您访问数据。如果你不能添加 getter,那可能是不可能的。
      • 除非它们在同一个包中,否则我应该提一下。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多