4

This is about the compareTo contract that classes can implement.

there is no way to extend an instantiable class with a new value component while preserving the compareTo contract, unless you are willing to forgo the benefits of object-oriented abstraction. The same workaround applies, too. If you want to add a value component to a class that implements Comparable, don’t extend it; write an unrelated class containing an instance of the first class. Then provide a “view” method that returns this instance. This frees you to implement whatever compareTo method you like on the second class, while allowing its client to view an instance of the second class as an instance of the first class when needed.

I have read Why can't I extend an instantiable class with a new value component while preserving the compareTo contract?. It helped answer one or two questions i had.But the below question still remains unanswered to me.

1) If i define the two classes as unrelated,i am free to implement the compareTo method as i want.Agree that.But how am i making the two classes have the is-a/parent-child relationship.Can someone explain whatever Joshua called the "view" method?

Community
  • 1
  • 1
Anusha Pachunuri
  • 1,389
  • 4
  • 18
  • 39

1 Answers1

4

Can someone explain whatever Joshua called the "view" method?

I will continue Jon Skeet's simple example from the answer that you linked in your post:

// In Jon's code, Person derives from NamedThing
class NamedThing {
    String name;
}

class Person extends NamedThing {
    Date dateOfBirth;
}

"Providing a view" rather than "extending" would mean designing your class hierarchy like this:

class NamedThing {
    String name;
}

class Person {
    private  NamedThing namedThing;
    // Here is the view method
    public NamedThing asNamedThing() {
        return namedThing;
    }
    // Here is a convenience method for accessing name directly
    public String getName() {
        return namedThing.name;
    }
    Date dateOfBirth;
}

This frees you up to implement a new compareTo inside the Person, because there is no requirement to stay compatible with the superclass. If you need to view your person as a NamedThing, call asNamedThing() to get a view of the person reduced to a thing with a name.

Note that since this is not an is-a relationship, the asNamedThing is somewhat misleading: you get the named thing inside the person, not the person who happens to be a named thing. This limits the applicability of compareTo: for example, you cannot sort persons among other NamedThings.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I couldn't think of a way to do the following with this approach. NamedThing thing = new Person(). Are you saying this syntax while creating person objects is not possible with this approach? – Anusha Pachunuri Jul 21 '13 at 20:02
  • @AnushaPachunuri Correct, that is one consequence of this approach. You need to do `Person p = new Person(); NamedThing personsThing = p.asNamedThing();` – Sergey Kalinichenko Jul 21 '13 at 20:08
  • And i can still use all polymorphism concepts as is?Lets say dynamic binding in method overriding? They are still achievable right? – Anusha Pachunuri Jul 21 '13 at 20:21
  • @AnushaPachunuri No, I think that's the point Joshua was trying to make: do not extend `Comparable` classes to add value components to it, leave the class as is. There would be no polymorphism with these new classes and the `Comparable` classes they contain. – Sergey Kalinichenko Jul 21 '13 at 20:30