4.1 Equality of value types and reference types
Take a close look at the following program which uses the == operator on integers.
Predict the result of the program. Compile and run the program, and explain the results. Were your predictions correct? |
Solution
We study the following program:
i == j is value comparison, and as such the value of i == j is true. First notice that object is an alias for System.Object. The expression m == n compares references because the two 5-values are boxed when assigned to values of a reference type, see the section about boxing and unboxing. The == operator in m == n is determined by the static type of m and n, namely object. For m and n of type object, == will lead to comparison of references. m and n reference two different objects (which hold the same value). Therefore the value of the boolean expression m == n is false. |
4.2 Are playing cards and dice immutable?
Evaluate and discuss the classes Die and Card with respect to mutability. Make sure that you understand what mutability means relative to the concrete code. Explain it to your fellow programmers! More specific, can you argue for or against the claim that a Die instance/value should be mutable? And similarly, can you argue for or against the claim that a Card instance/value should be mutable? Why is it natural to use structs for immutable objects and classes for mutable objects? Please compare your findings with the remarks in 'the solution' when it is released. |
Solution
I find it reasonable that a Die is mutable. Each time we toss it we change/mutate its state. I do not think it is justifiable to have a mutable Card class. It would be strange - and against our intuition - to change the suite or value of an already existing card. The state of a Card is never changed. In the code, mutability reveals itself by assignments to the instance variables in the bodies of methods. Why is it natural to use structs for immutable objects and classes for mutable objects? Classes are reference types. There are often several references to the same objects (this is called aliasing). If the state of the object is update/mutated it can be observed via all the references. Instances of classes are only copied on demand (for instance via Clone or via use of a copy constructor). In your client program you need to be aware of this. Due to aliasing via references, the copy of an object cannot always be used in place of the original object! The identity of class instances are strong. In contrast, structs are value types. Instances of structs are copied a lot - by assignments, parameter passing, and by return. A copy of a struct instance is just as good as the original. In your client program, you should not notice if you deal with the original struct instance or a copy of it. Mutation is dealt with by creating a "mutated copy". The identity of struct instances are weak. If you want to mutate an object you should be very conscious about making copies of the object. Such consciousness can be handled with classes, but not with structs. |
4.3 Privacy Leaks
The starting point of this exercise is the observations about privacy leaks on the accompanying slide. Make sure that you understand the problem. Test-drive the program (together with its dependent Person class and Date class) on your own computer. If you have not already done so, read the section about privacy leaks in the textbook! Find a good solution to the problem, program it, and test your solution. Discuss to which degree you will expect that this problem to occur in everyday programming situations. |
4.4 Mutable and immutable Point objects with Move methods
On the slides about mutable and immutable structs we have illustrated two versions of struct Point with two different implementations of the Move method. In the first struct, Move mutates the x and y coordinates and it returns this- the current object. The second struct is immutable and Move returns a new instance of Point which is moved relative to the receiver of the Move message. For both versions of Point we use the same client class, which sends Move messages to different points. In the lecture - and in the textbook - the differences between the first struct and the second struct has been explained relative to the client class. Be sure that you understand the difference! Now, you are asked to implement version 1 and version 2 of Point from above with classes instead of structs. Compile and run each of them relative to the given client class. In each of the two cases explain the behavior of the Move methods in the classes. In each of the two cases, explain how many instances of class Point there is created. |
Solution
The first class is the following:
In the client program
only a single Point object is involved. As expected, it is moved from (1.0, 2.0) via (4.0, 6.0) to (9.0, 12.0). In the similar version, where Point is implemented as a struct, the problem was that the expression p1.Move(3.0, 4.0) returns a copy of a point, which subsequently is moved. This problem does not occur when we work with classes. The client program only creates a single Point object. In the next version of the Point class
each Move message creates a new Point object. Therefore, the client class
creates three instances of class Point. First (1.0, 2.0) is referred from p1. The expression p1.Move(3.0, 4.0) returns a new Point object located at (4.0, 6.0). This point receives the message Move(5.0, 6.0). This allocates the third Point object located at (9.0, 12.0). A reference to this object is assigned to p2. Hereby p2 refers the point located at (9.0, 12.0). The two copies are wasteful and actually not needed. With use of classes, we do not encounter the same problem as we did with the first version of the struct Point. All taken together, I recommend the second version of struct Point and the first version of class Point. You should use program immutable types with structs and mutable types with classes. |
4.5 Pyramid BankAccounts
This exercise can be seen as a continuation of the bank account exercise in which we supplied a bank account with a backup account. The primary purpose of the exercises is to train recursive object-oriented programming. We organize bank accounts in a tree structure (called a pyramid) in which each bank account may have two sons which are also bank accounts. The money in the account are somehow distributed on the accounts of the pyramid. Program a version of class BankAccount with an owner, a balance, and possible references to two additional bank accounts: leftAccount and rightAccount. A skeleton of this class is provided together with a client program. You can assume that an account is either a leaf or the account has two sons.
|
Solution
Here is my solution:
|
Generated: Monday February 7, 2011, 12:14:35