Mike Meyer <[EMAIL PROTECTED]> wrote: > [EMAIL PROTECTED] (Alex Martelli) writes: > > Mike Meyer <[EMAIL PROTECTED]> wrote: > >> My standard object interface is modeled after Meyer's presentation in > >> OOSC: an objects state is manipulated with methods and examined with > >> attributes; manipulating attributes doesn't change the internal state > >> of the object. This makes it possible to change the internal > >> representation of a class without having to change all the clients of > >> the class to match. ... > On the other hand, Eiffel specifically forbids setting attributes > directly, except for the object they belong to. This is done to > enforce the design goals I stated above: attributes are the "readouts"
We must have a different meaning in mind for the word "goal"; I take it to mean, as a web definition says, "the state of affairs that a plan is intended to achieve". By this definition, your second quoted sentence identifies a goal, but the former one doesn't -- it's a MEANS, not an END, as strongly confirmed by the words "This makes it possible to...". Enabling internals' changes is a goal, and an important one; doing so by forbidding the setting of attributes is one way to help achieve it, but properties are another way, and as a matter of language design it appears to me to be a better approach. I haven't used Eiffel "in anger", just evaluated and rejected it years ago for an employer, but I have used other languages such as ObjectiveC which follow a similar approach, so my preference is based on some experience (Ruby, though strongly influenced by Smalltalk, does let you define attribute-setter methods, with a net effect similar to Deplhi's or Python's properties). > for an object, and methods are the knobs/dials/etc. This also ties in > with the compiler having facilities to check class invariants. If you > allow assignments to attributes in other classes, the assignments have > to generate code to check the invariants every time you have such an > assignment, otherwise a future attribute read may come from an object > in an invalid state. If you only allow attributes to be set by the > owning objects methods, then you only have to check the invariants on > method exit. What classes' invariants do you have to check in those cases? E.g., consider zim.foo.bar.baz() -- you do have to check the invariants of bar, foo AND zim, right? And you must do it with code placed inline after this specific call, since not all calls to that baz method must check invariants in foo and zim. So, what's different about having to generate just the same inline code for, say, zim.foo.bar=baz ? Since your compiler must be ready to generate such checks anyway, forbidding the second form appears to have no pluses. Or, in other words, having to spell zim.foo.bar=baz as zim.foo.set_bar(baz) [[and having to code boilerplate to implement set_bar]] is a style-choice (common to Eiffel and Smalltalk, and others) which I consider inferior to the alternative choice you find in Ruby or Python [[allowing autogeneration of the implied attribute-setter method if necessary]]. > Different idioms for different languages. Trying to write Python in > Eiffel doesn't work any better than trying to write C++ in Python. Absolutely, but here I was discussing language design, not usage of languages whose design is an external "given". Alex -- http://mail.python.org/mailman/listinfo/python-list