【问题标题】:using equals or instanceof in toString在 toString 中使用 equals 或 instanceof
【发布时间】:2013-09-19 14:40:49
【问题描述】:

好吧,伙计们,我有一个带有“MartianManager”类的程序:*注意代码不完整仍然有一些缺失的部分只是提供了整个代码以供参考,以了解完成后的外观

import java.util.ArrayList;

public class MartianManager {
private ArrayList<Martian> martians;
private ArrayList<Martian> teleporters;

public void addMartian(Martian m) {
    martians.add(m);
    if(m instanceof GreenMartian)
        teleporters.add(m);
}
//public Object clone() {

public Martian getMartianClosestToID(int id) {  
}
public void groupSpeak() {
    for(Martian m : martians) {
        m.speak();
    }
}
public void groupTeleport(String dest) {    
}
}

和火星类:

public abstract class Martian implements Cloneable {
int id;

public Martian(int id) {
    this.id = id;
}
public Object clone() throws CloneNotSupportedException {
    return super.clone();
}
public int getId() {
    return id;
}
public boolean equals(Object o){
    return this.getId() == ((Martian)o).getId();    
}
public abstract void speak();

public String toString(){
    String str = "";
    if (this instanceof GreenMartian) {
        str = "Green martian" + id;
    }
    if (this instanceof RedMartian) {
        str = "Red martian" + id;
    }
    return str;
}       
}

它是用 GreenMartian 扩展的:

public class GreenMartian extends Martian implements ITeleport{

public GreenMartian(int id) {
    super(id);
}
public void speak() {
    System.out.println(id + "Grobldy Grock");
}
public void teleport(String dest) {
    System.out.println(id + "teleporting to " + dest);
}

}

还与 RedMartian 一起扩展:

public class RedMartian extends Martian {

public RedMartian(int id) {
    super(id);
}
public void speak() {
    System.out.println(id + "Rubldy Rock");
}
}

我其实有几个问题,但现在我的问题是在 Martian 类的 toString 中。它应该返回一个像这样的字符串:“Red [or Green] martian” +id。我需要确定火星人的类型,我开始使用 instanceof 但就像这样“火星人无法解析为变量”。我正在尝试确定这是否是最好的方法,或者 equals() 是否是确定类型的最佳方法?

这也是我第一次使用“克隆”,所以不确定它是如何工作的,但想到有没有办法确定“克隆”是什么并以这种方式确定?

感谢您的所有帮助!

【问题讨论】:

    标签: java clone equals tostring instanceof


    【解决方案1】:

    没有

    public String toString(){
        String str;
        if (Martian instanceof GreenMartian) {  
    }
    

    abstract Martian 上课是个坏主意。你不希望你的父类依赖它的子类。

    改为在每个子类中实现toString() 方法,并让多态性发挥作用


    如果你必须这样做

    if (Martian instanceof GreenMartian) {  
    

    错了。你就这样使用instanceof

    instanceOfClass instanceof SomeClass
    

    在这种情况下,您会使用 this 关键字获得对 instanceOfClass 的引用,因为您是在实例上调用该方法

    this instanceof GreenMartian
    

    【讨论】:

    • 好吧,这是有道理的,我已经用 instanceof 更新了我的代码。这是它应该看起来的样子,还是可以再简化一点?
    • @user2745043 不,不。检查维基百科中的多态性,你会得到它
    • @user2745043 它在语法上是正确的(假设您的导入是正确的),但这是一个非常糟糕的主意。
    【解决方案2】:

    你真的不应该让父类引用任何扩展它的类。这是不好的做法(并且可能实际上不起作用,我没有测试过)。你真的应该重写每个扩展类中的 toString 函数。

    public class GreenMartian extends Martian implements ITeleport{
    
        public GreenMartian(int id) {
            super(id);
        }
        public void speak() {
            System.out.println(id + "Grobldy Grock");
        }
        public void teleport(String dest) {
            System.out.println(id + "teleporting to " + dest);
        }
    
        @Override
        public String toString() {
             return "GreenMartian: whatever info you'd like to include.";
        }
    
    }
    

    现在,如果您希望所有子类都采用类似的格式,您有两种选择。一种是调用父类的 toString 方法,并将其添加到子类的 toString 方法中。

    @Override
    public String toString() {
        return super.toString() + "GreenMartin: info.....";
    }
    
    //The parent toString could look like this:
    @Override
    public String toString(){
        return "Martian( ... put any parent class info here, id ect)";
    }
    

    GreenMartian toString 调用的最终输出可能如下所示:

    Martian(id:23) GreenMartian(planet:greenburg)
    

    第三种选择是在父类中使用通用字符串格式。例如,在父类中,包含这个属性:

    protected static final String format = "Class: %s, id: %s, info: %s";
    

    然后,在 toString 的子类中,你可以这样做:

    @Override
    public String toString() {
        return String.format(format,this.getClass().toString(),id,myInfo);
    }
    

    【讨论】:

    • 好的,如果我使用您的第一个示例,并且只覆盖每个子类的 toString,它在父类中的外观如何?我从来没有使用过“格式”,所以我不确定第一个格式是否也一样。
    • 父类的 toString 可以看起来像你想要的那样。它可能应该包含父类所拥有的任何信息,并且采用一种显而易见的格式。我将更新我的示例。
    • 好吧,这就是我的想法,因为我在子类中覆盖了 toString,所以父类 toString 中的任何内容都不会显示出来吗?
    • 是的,那是正确的。请注意,您可以使用“super”来调用被覆盖方法的父方法。如果您真的需要,这使您可以访问父 toString。
    【解决方案3】:

    您可以使用String name = this.getClass().getSimpleName() 获取您的班级名称。然后您可以检查name.substring(0,1).equals("G")name.substring(0,1).equals("R") 来检测红色或绿色。

    【讨论】:

    • 这真是糟糕的 OO 设计。
    • 这真是糟糕的 OO 设计并且效率低下。为什么要创建子字符串并在它们上调用equals 来比较单个char?为什么不name.charAt(0)=='G'?太明显了?
    【解决方案4】:

    FWIW,它应该是if (this instanceof GreenMartian) - 但恕我直言,每当您想使用这种向下转换(向上转换??)时,它都是糟糕的 OO 设计的标志。而是为你的火星人写一个专门的toString()方法。而且你真的应该在你的equals() 方法中检查o==null

    【讨论】:

      【解决方案5】:

      火星人不是变量。试试这个:

      如果(GreenMartian 的这个实例)

      【讨论】:

      • 虽然你是对的 - 请不要这样做。请参阅 Sotirios'/aglassman 的答案并使用多态性。
      • 完全正确,但他想知道为什么 Martian 无法解析为变量
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 2021-10-31
      • 2012-11-09
      • 2021-11-27
      相关资源
      最近更新 更多