subtype object .equals() supertype object

Discussion in 'Plugin Development' started by Regenwurm97, Dec 29, 2016.

Thread Status:
Not open for further replies.
  1. Offline

    Regenwurm97

    Hey there!

    I've been struggling for a day on this now and I can't find a way to correctly implement what I need....
    I have 2 object types: Location (org.bukkit) and CustomLocation EXTENDS Location. So CustomLocation is a direct subtype of Location but defines no new attributes, just some additional behavior.

    I want to check for equality of a Location object and CustomLocation object just by comparing both as the .equals() method of Location would normally do...
    So subtype.equals(supertype); or vice-versa should return true, if the essential values of the two locations are the same (as always). I've therefore overridden the .equals() method of the subtype class
    Here are some ways I've tried:

    Code:
                System.out.println("Checking equals: " + loc.equals(super.getBlock().getLocation()));
                System.out.println("Checking equals: " + super.equals(loc));
                System.out.println("Checking equals: " + loc.equals(this));
                System.out.println("Checking equals: " + loc.equals((Location) this));
    The output is:

    Code:
    true
    false
    false
    false
    I cannot believe the first option is the only and right way to achieve what I want...This is a super weird hack-around and it's just there to make Java finally understand to compare the f**king Location and NOT the subtype :D
    Hope you guys can help me out here... :)

    BTW: This is the equals implementation by now:


    Code:
        /**
         * Compare two locations for equal by their location
         */
        @Override
        public int hashCode() {
         
            return super.hashCode();
         
        }
     
        @Override
        public boolean equals(Object obj) {
         
            if(obj == null) return false;
         
            if(obj instanceof Location) {
             
                Location loc = (Location) obj;
             
                System.out.println("Checking advanced equals: " + loc.equals(super.getBlock().getLocation()));
                System.out.println("Checking advanced equals: " + super.equals(loc));
                System.out.println("Checking advanced equals: " + loc.equals(this));
                System.out.println("Checking advanced equals: " + loc.equals((Location) this));
             
                return loc.equals((Location) this);
             
            }
         
            else return false;
         
        }
     
  2. @Regenwurm97
    If we look at the equals method in the Location class, it should become apparent why it doesn't work:
    Code:java
    1. public boolean equals(Object obj) {
    2. if(obj == null) {
    3. return false;
    4. } else if(this.getClass() != obj.getClass()) {
    5. return false;
    6. } else {
    7. Location other = (Location)obj;
    8. return this.world != other.world && (this.world == null || !this.world.equals(other.world))?false:(Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)?false:(Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)?false:(Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)?false:(Float.floatToIntBits(this.pitch) != Float.floatToIntBits(other.pitch)?false:Float.floatToIntBits(this.yaw) == Float.floatToIntBits(other.yaw)))));
    9. }
    10. }
    Unlike most equals implementations, this one compares the Class instead of making an instanceof check, which means that subclasses won't work. This is rather curious, as it must be a consious decision, but I can't think of any reason why this is done, although there probaby is one. If you want to make your equals method work, you're going to have to write your completely own and not use the superclasses method.
     
  3. Offline

    mythbusterma

    @AlvinB

    It makes sense if you think about it. This way someone couldn't create a subclass of location whose behavior could be different, then use it to assign Player's locations and things like that.
     
  4. Offline

    Regenwurm97

    Ah I see, yeah that makes sense. Never hopped into the Location class to see it's implementation - thanks for your support guys! I found a work-around :)
     
  5. @mythbusterma
    Well, if that were the case, wouldn't they just make the Location class final so you can't extend it? I'm thinking it must be something more specific, as it's only the equals method that does this..
     
Thread Status:
Not open for further replies.

Share This Page