Hirdetés

Új hozzászólás Aktív témák

  • Szmeby
    tag

    Sziasztok!

    Ismét segítségeteket kérném.

    Van egy pont osztályom:

    public class Point{
    private int x;
    private int y;

    public Point(int x, int y){
    this.x = x;
    this.y= y;
    }

    public int getX(){
    return this.x;
    }

    public int getY(){
    return this.y;
    }

    public boolean equals(Object other){
    Point otherPoint = (Point) other;
    return getX() == otherPoint.getX() && getY() == otherPoint.getY();
    }

    public double getDistance(Point other){
    return Math.sqrt( Math.pow(getX() - other.getX(), 2) + Math.pow(getY() - other.getY(), 2));
    }

    public String toString(){
    return "(" + getX() +", " + getY() + ")";
    }


    }

    Van egy pontokból álló vonallánc osztályom:

    import java.util.ArrayList;
    public class PolyLine{

    private ArrayList<Point> points = new ArrayList<Point>();


    public PolyLine(ArrayList<Point> points){
    this.points = points;

    for (int i = 0; i < points.size()-1; i++){
    if (!add(points.get(i))){
    points.remove(i);
    i--;
    }
    }

    }

    public ArrayList<Point> getPoints(){
    return points;
    }

    public boolean equals(Object other){
    return points.equals(other);
    }

    public boolean add(Point p){

    int pos = points.indexOf(p);

    return pos != -1 && !points.get(pos+1).equals(p);

    }

    public String toString(){

    String a = "[";

    String b = "" ;

    for (int i = 0; i < points.size()-1; i++){
    b = b + points.get(i).toString()+ ", ";
    }

    String c = points.get(points.size()-1).toString() + "]";

    return a + b + c;

    }



    }

    A baj az, hogy a két vonallánc összehasonlításánál az equals false-t dob, amikor azok megegyeznek. Az ismétlődések nem számítanak, azt a vonallánc constructorja kiszedi. A fejlécek fixek, azokat nem lehet változtatni. A sejtesem az, hogy point osztály equals metódusával számol és nem a beépített arraylistessel.

    Itt hozza a teszt:

    import java.util.ArrayList;
    public class Bsp10{

    public static void main(String[] args){


    ArrayList<Point> points = new ArrayList<>();
    points.add(new Point(292, -457));
    points.add(new Point(292, -457));
    points.add(new Point(292, -457));
    points.add(new Point(17, -277));
    points.add(new Point(-942, -103));
    points.add(new Point(-557, -18));

    PolyLine polyLine = new PolyLine(points);

    ArrayList<Point> points2 = new ArrayList<>();
    points2.add(new Point(292, -457));
    points2.add(new Point(17, -277));
    points2.add(new Point(-942, -103));
    points2.add(new Point(-557, -18));

    PolyLine polyLine2 = new PolyLine(points2);

    System.out.println(polyLine);
    System.out.println(polyLine2);
    System.out.println(polyLine.equals(polyLine2));

    }
    }

    Köszi előre is!

    Ezért ne kövesd el te azt a hibát, amit a java megalkotói, hogy túl általános típust használsz. :)
    Jó, tudom, csak kompatibilitás, de akkoris.

    Szóval a probléma a PolyLine.equals-ban van. Mivel a szignatúrája szerint Objectet vár, az ember bármit beadhat. És hidd el, be is fog. Amin aztán az egész cucc megfekszik (pl. ClassCastException-nel), ha nem figyelsz. Rosszabb esetben - mint most is - működik tovább hibásan.
    Javaslom, minden equals metódusodban ellenőrizni a bejövő paraméter típusát. Ha nem jó típus, akkor false, ha jó típus, akkor pedig tessék castolni, és aztán hasonlítgatni. Könnyebben kibukik, hogy a beadott PolyLine nem is ArrayList, amivel hasonlítani akarod.
    Egyébként az equals, hashcode metódusokat egy IDE szépen ki is generálja neked, van rá menüpont.

    Szóval listát a listával:

    public boolean equals(Object obj){
    if (obj == this) {
    return true;
    }
    if (obj == null) {
    return false;
    }
    if (getClass() != obj.getClass()) {
    return false;
    }
    PolyLine other = (PolyLine) obj;
    return points.equals(other.points);
    }

    Ha nem kellenek az ismétlődések, miért nem egy rendezett Setet használsz erre a célra? LinkedHashSet, vagy valami ilyesmi. Ő magától megcsinálja.

    Pár megjegyzés:
    - Osztályon belül felesleges gettereket használnod, simán lehet hivatkozni a field-ekre, pl.:
    return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));

    - Ha az objektum állapota nem változhat, akkor érdemes a field-eket final-ra állítani, így még véletlenül sem fogod tudni tönkretenni az objektumaidat. Továbbá egy ilyen tipikus value object esetén én még a getterek elhagyását is megkockáztatnám, valahogy így:
    public class Point{
    public final int x;
    public final int y;

    public Point(int x, int y){
    this.x = x;
    this.y= y;
    }

    public boolean equals(Object other){
    // ...
    }

    public double getDistance(Point other){
    // ...
    }

    public String toString(){
    // ...
    }
    }

    - Ne félj interfészt használni, ahol lehet, könnyebben cserélgetheted majd mögötte az implementációt. Ha nem akarod cserélgetni, akkor sem árt, mert idővel rááll a kezed, és nem kell folyton törnöd az APIt egy kis módosítás miatt.
    Erre gondolok:
    private ArrayList<Point> points = new ArrayList<Point>();
    // helyett
    private List<Point> points = new ArrayList<Point>();
    // esetleg (attól függ, milyen funkcionalitást vársz el tőle, legyen-e rendezett, stb)
    private Collection<Point> points = new ArrayList<Point>();

    - Ciklusban Stringeket konkatenálni + jellel nem szép dolog, brutálisan pazarló. Minden egyes konkatenáció egy újabb és egy újabb Stringet hoz létre, amit aztán a következő körben el is dob, mert csak átmenetileg volt rá szükség. StringBuilder javallott és annak append metódusa. Vaaagy használod a listák toString metódusát, mert van. :)

Új hozzászólás Aktív témák