子类使用父类类型实现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
相关产品推荐
相关产品推荐

