What is the output from the following program?
namespace animal_farm
class animal
public static method op_Equality, boolean
in req animal1, @animal
in req animal2, @animal
proc
mreturn true
endmethod
endclass
class pig extends animal
public static method op_Equality, boolean
in req animal1, @pig
in req animal2, @animal
proc
mreturn (animal2 .is. pig)
end
endclass
main
record
an_animal ,@animal
a_pig ,@pig
proc
open(1,o,"TT:")
an_animal = new animal()
a_pig = new pig()
if (an_animal == a_pig) then
display(1, "All animals are equal, ")
else
display(1, "Not all animals are equal, ")
if (a_pig == an_animal) then
writes(1, "no matter who comes first")
else
writes(1, "some animals are more equal than others")
end
endnamespace
a. “All animals are equal, no matter who comes first”
b. “All animals are equal, some animals are more equal than others”
c. “Not all animals are equal, no matter who comes first”
d. “Not all animals are equal, some animals are more equal than others”
Explanation
In the first test, the first operand is of type animal and the second operand is of type pig. Neither class defines an op_Equality having that order of operands, but since pig extends animal, the op_Equality for class animal will do. That returns true, so “All animals are equal, “ displays first. In the second test, the order of operands is reversed, which more closely matches the definition of op_Equality for the pig class. In that class, both operands are equal only if they are both members of the pig class. That isn’t the case here, so “some animals are more equal than others” displays next.
This example shows how operators can be overloaded, how static methods can be inherited, and how the types of the operands are used to select the best operator method. It also showcases the .IS. operator for determining class membership.
When defining equality between two different classes, you probably want to define both orders of operands. For instance, to get result (d) above, we would need to define a second version of op_Equality in class pig that switches the order of the operands and tests the first one for “.is. pig”. To get result (a) above, we would need to omit the op_Equality in class pig altogether. How to arrive at result (c) can be left as an exercise for the reader.
To make usage sane, whenever you define op_Equality you probably also want to define a corresponding op_Inequality. We recommend that you always make equality tests work consistently in both directions, so you don’t find yourself in the middle of a class struggle.