←Older revision |
Revision as of 09:08, 6 September 2013 |
Line 37: |
Line 37: |
| | | |
| This is approach suitable for [[wikipedia:Algebraic_types|algebraic types]], but in [[OOP]] we might want some subclasses of ''Date'' to still be equal to plain ''Date'' instances. For example intervals of length zero may need to be equal to the ''Date'' object with the same beginning ''time''. | | This is approach suitable for [[wikipedia:Algebraic_types|algebraic types]], but in [[OOP]] we might want some subclasses of ''Date'' to still be equal to plain ''Date'' instances. For example intervals of length zero may need to be equal to the ''Date'' object with the same beginning ''time''. |
| + | |
| + | ==== Knowing More ==== |
| | | |
| Then it comes to question: ''Who knows more?'' As discussed in [[SuperVsInner]] essay in [[Java]] it is safe to assume that ''subclasses know more'' - as such it should be the subclass who handles the ''equals'' call: | | Then it comes to question: ''Who knows more?'' As discussed in [[SuperVsInner]] essay in [[Java]] it is safe to assume that ''subclasses know more'' - as such it should be the subclass who handles the ''equals'' call: |
Line 42: |
Line 44: |
| <source lang="java"> | | <source lang="java"> |
| class Date { | | class Date { |
- | private long time;
| + | private final long time; |
| | | |
- | public boolean equals(Object o) {
| + | public Date(long time) { |
- | if (o instanceof Date) {
| + | this.time = time; |
- | if (o.getClass() != getClass() && getClass().isAssignableFrom(o.getClass())) {
| + | } |
- | return o.equals(this); // [1]
| + | |
- | } else {
| + | @Override |
- | return time == ((Date)o).time;
| + | public boolean equals(Object o) { |
- | }
| + | if (o instanceof Date) { |
| + | if (o.getClass() != getClass() && getClass().isAssignableFrom(o.getClass())) { |
| + | return o.equals(this); // [1] |
| + | } else { |
| + | return time == ((Date) o).time; |
| + | } |
| + | } |
| + | return false; |
| } | | } |
- | return false;
| |
- | }
| |
| } | | } |
| | | |
| class Interval extends Date { | | class Interval extends Date { |
- | private int length;
| + | private final int length; |
| | | |
- | public boolean equals(Object o) {
| + | public Interval(long time, int length) { |
- | if (o instanceof Interval) {
| + | super(time); |
- | if (o.getClass() != getClass() && getClass().isAssignableFrom(o.getClass())) {
| + | this.length = length; |
- | return o.equals(this); // [1]
| + | } |
- | } else {
| + | |
- | return time == ((Interval)o).time && length == ((Interval)o).length;
| + | @Override |
- | }
| + | public boolean equals(Object o) { |
| + | if (o instanceof Interval) { |
| + | if (o.getClass() != getClass() && getClass().isAssignableFrom(o.getClass())) { |
| + | return o.equals(this); // [1] |
| + | } else { |
| + | return super.equals(o) && length == ((Interval) o).length; |
| + | } |
| + | } |
| + | return length == 0 && super.equals(o); // [2] |
| } | | } |
- | return length == 0 && super.equals(o); // [2]
| |
- | }
| |
| } | | } |
| | | |
| class SerializableDate extends Date implements java.io.Serializable { | | class SerializableDate extends Date implements java.io.Serializable { |
| + | public SerializableDate(long time) { |
| + | super(time); |
| + | } |
| } | | } |
| | | |
- | assert !new Date(323).equals(new Interval(323, 10));
| + | assertFalse(new Date(323).equals(new Interval(323, 10))); |
- | assert new Date(323).equals(new Interval(323, 0));
| + | assertTrue(new Date(323).equals(new Interval(323, 0))); |
- | assert new Date(323).equals(new SerializableDate(323));
| + | assertTrue(new Date(323).equals(new SerializableDate(323))); |
| </source> | | </source> |
| | | |
| The check ''[1]'' makes sure the comparing is always done by subclass. Then the subclass can either do nothing (like the ''SerializableDate'') and inherits working equals from the superclass, or the subclass can use its special knowledge (like ''Interval'' at line ''[2]'') and be equal to super class in some special conditions (here when the ''length'' is zero). | | The check ''[1]'' makes sure the comparing is always done by subclass. Then the subclass can either do nothing (like the ''SerializableDate'') and inherits working equals from the superclass, or the subclass can use its special knowledge (like ''Interval'' at line ''[2]'') and be equal to super class in some special conditions (here when the ''length'' is zero). |