Python from Wise Guy's Viewpoint

Fergus Henderson fjh at cs.mu.oz.au
Mon Nov 3 16:49:56 CET 2003


Pascal Costanza <costanza at web.de> writes:

>Fergus Henderson wrote:
>
>> 		static void test_employed() {
>> 			class Person {
>> 				public String name;
>> 				Person(String n) { name = n; }
>> 			};
>> 			Person joe = new Person("joe");
>> 			System.out.println("-> hire joe");
>> 			hire(joe, 60000);
>> 			System.out.println("name: " + joe.name);
>> 			System.out.println("class: "
>> 					+ joe.getClass().getName());
>> 			Employee e = (Employee) employees.get(joe);
>						^^^^^^^^^^^^^^^^^^
>This part is not domain-specific, but shows that your abstraction leaks. 
>I.e. the client of your interface has to remember how the employee 
>abstraction is implemented in order to use it correctly.
>
>In my original example, I was able to just call (company joe) and 
>(salary joe) (or, in Java syntax, this would be joe.salary and 
>joe.company). I.e., I don't have to know anything about the internal 
>implementation.

Well, you have a point, I didn't encapsulate the use of the Hashtable.
I can do that quite easily:

		static Employee employee(Object obj) {
			return (Employee) employees.get(obj);
		}

Then the code there could become as follows.

		System.out.println("employed: " +
			(employee(joe) != null ? "yes" : "no"));
		System.out.println("company: " + employee(joe).company);
		System.out.println("salary: " + employee(joe).salary);

If you prefer, you can make make it simpler still,

		System.out.println("employed: " +
			(employeed(joe) ? "yes" : "no"));
		System.out.println("company: " + company(joe));
		System.out.println("salary: " + salary(joe));

by defining suitable methods:

		static bool employed(Object obj) {
			return employee(obj) != null;
		}
		static String company(Object obj) {
			return employee(obj).company;
		}
		static int salary(Object obj) {
			return employee(obj).salary;
		}

Now, my guess is that you're still going to be complaining about the
abstraction leaking, but I don't think such complaints are valid.
Yes, the syntax is different than a field access, but that's not
important.  The client is going to need to know the names of the
attributes or methods they want to use anyway; as long as they need to
know whether the name of the entity is "wage" or "salary", it doesn't make
a significant difference that they also need to know whether the interface
to that entity is a field, a member function, or a static function.

And of course, this syntax issue is language-specific.  In Mercury
and Haskell, the same syntax is used for field access, method call,
and function call, so the issue doesn't arise!

>You can't implement unanticipated optional features in a statically 
>typed language that doesn't involve leaking abstractions.

Not true.  See above.

>I would still need to remember what features happen to be kept external 
>from my objects and what not.

No, that's not what you need to remember.  You just need to remember the
names of the features, and for each feature what kind of feature it is:
whether it is a field, an instance method, or a static method.
If it is a field, you know it is kept inside the object, but in
the other two cases the implementation is encapsulated -- the user
can't tell where the data is stored.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.




More information about the Python-list mailing list