You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类使用父类类型实现Comparable接口的问题及解决

问题:自定义compareTo方法无法触发的排查与解决

尝试给Rational类实现Comparable接口并重写compareTo方法,代码逻辑看似没问题,但测试时遇到两个问题:

  • 直接调用两个Rational对象的compareTo方法,抛出“Symbol not found”错误;
  • 尝试把Rational转为String后调用compareTo,发现自定义的compareTo方法完全没执行(修改方法参数返回值始终是2),但equals方法对比正常。

初始代码

package app.exercise.testing;
import app.exercise.algebra.*;
import java.lang.Comparable;

public class compRational extends Rational implements Comparable<Rational>{

   public int compareTo(Rational y){
        System.out.println("Troubleshoot: "+(int)this.getN()*(int)y.getD()+ " "+(int)y.getN()*(int)this.getD());
        return Integer.compare((int)this.getN()*(int)y.getD(),(int)y.getN()*(int)this.getD());

    }
    //Testing

    public static void main(String args[]){
        Rational test=new Rational(3,8);
        Rational test2=new Rational(10,3);
        Rational test3=new Rational(3,8);
        // Compare

        System.out.println("Compare Test: "+test.compareTo(test2));
        if((test.toString().compareTo(test3.toString())==0) == test.equals(test3)){
            System.out.println("compare test 2: "+true);
        }
    }
}

问题原因

调试打印从未执行,说明实际调用的不是自定义的compareTo方法:

  • test、test2都是Rational类型实例,而非compRational类型,父类Rational本身没有定义compareTo方法,直接调用会报错;
  • 转为String后调用的是String类的compareTo方法,自然不会触发自定义逻辑。

解决方案

将compareTo方法直接重写在Rational父类中,让所有Rational实例都能调用该方法;同时让compRational继承Rational并实现Comparable接口,继承父类的compareTo方法。

修复后的Rational类代码

public class Rational extends BasisFraction{
    private long numerator;
    private long denominator;
    
    /**
    Implementierung von setND aus @see BasisFraction um Parameter eines @see Rational Objekts zu verändern
    Parameter
    @param numerator neuer Zähler des Objekts
    @param denominator neuer Nenner des Objekts
    
    */
    
    public int compareTo(Rational y){
        return Integer.compare((int)this.getN()*(int)y.getD(),(int)y.getN()*(int)this.getD());
    }   
    
    protected void setND (long numerator, long denominator ){
        long teiler=ggT(numerator, denominator);
        this.numerator=numerator/teiler;
        this.denominator=denominator/teiler;
    }
    
    /**Default Konstruktor für @see Rational
    */
    public Rational(){
        setND(1,1);
    }
    
    /**
    Konstruktor für @see Rational
    kürzt mit @see ggT weitmöglichst, setzt nur Zähler negativ falls notwendig
    Parameter
    @param n Nenner
    @param d Zähler
    */
    public Rational(long n,long d){
        long teiler=ggT(n,d);
        n=n/teiler;
        d=d/teiler;
        if(d < 0){
            setND(-n,-d);
        }
        else{
        setND(n, d);
        }
    }
    
    /**
    Kehrwert
    @return Kehrwert übergebender rationaler Zahl
    */
    public Fractional reciprocal(){
        Rational rückgabe= new Rational(this.denominator, this.numerator);  
        return rückgabe;
    }
    
    /**
    * *(-1)
    @return übergebende rationale Zahl *(-1)
    */
    public Fractional negation(){
        Rational rückgabe=new Rational(this.numerator*-1,this.denominator);
        return rückgabe;
    }
    
    /**
    getter Nenner
    
    @return Nenner
    */
    public long getD(){
        return this.denominator;
    }
    
    /**
    getter Zähler
    
    @return Zähler
    */
    public long getN(){
        return this.numerator;
    }
    
    /**größter gemeinsamer Teiler
    @param n Zahl 1
    @param d Zahl 2
    */
    public static long ggT(long n, long d){
        if(d == 0)
                    return n;
            return ggT(d, n%d);
    }
    
    /**
    Umwandlung eines @see Rational Objekts in einen String
    Rückgabe
    @return Zähler / Nenner
    */
    public String toString(){
        return "" +getN() + "/"+getD();
    }
    
    /**
    Kopiert übergebendes Objekt
    Rückgabe
    @return neues Objekt mit gleichen Parametern
    */
    public Rational clone(){
        Rational rückgabe=new Rational(this.getN(), this.getD());
        return rückgabe;
    }
    
    /**
    überprüft ob 2 Objekte gleich sind, also dieselben Parameter enthalten
    Parameter
    @param y @Rational Objekt mit dem verglichen wird
    @return bool
    */
    public boolean equals(Rational y){
        if(this.getN()==y.getN()&&this.getD()==y.getD()){
            return true;
        }
        else
            return false;
    }
    
    /**
    berechnet Hashcode eines Objekts, indem Zähler+Nenner quadriert und mod 10 gerechnet wird
    @return HashCode
    */
    public int hashCode(){
        return (int)Math.pow(this.getN()+this.getD(),2)%10;
    }
}

最终带测试功能的compRational类代码

package app.exercise.algebra;
import java.lang.Comparable;

public class compRational extends Rational implements Comparable<Rational>{
 public static void main(String args[]){
        Rational test=new Rational(3,8);
        Rational test2=new Rational(10,3);
        Rational test3=new Rational(3,8);
        // Compare

        System.out.println("Compare Test: "+test.compareTo(test2));
        if((test.compareTo(test3)==0) == test.equals(test3)){
            System.out.println("compare test 2: "+true);
        }
    }
}

内容的提问来源于stack exchange,提问作者Leon Preuße

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:51:01