[FIX][KCP] KCP-0112-FixCanUnderstand

goran.krampe at bluefish.se goran.krampe at bluefish.se
Tue Dec 16 09:02:55 UTC 2003


Hi all!

This post doesn't add anything of real value to the discussion - Richard
in his usual way emptied the bottle of all interesting arguments. But I
wanted to chime in to show that I agree with Richard. :)

"Richard A. O'Keefe" <ok at cs.otago.ac.nz> wrote:
> With respect to #respondsTo: and #canUnderstand:
> I feel rather cross, because this issue has *already* been discussed.
> I provided an [ENH] which defined
> 
>     Object>>honestlyRespondsTo:
>     Behavior>>canHonestlyUnderstand:
> 
> I can well believe that my code was buggy, but it's like a slap
> in the face to have the entire discussion and code ignored.

Mmmm, I recall that post. Richard, I agree it can be annoying - but this
list is overflowing with stuff and since we haven't pulled off TFNR yet
(working hard on it - the "staking out" is close to finished btw) things
unfortunately ends up "between the chairs".

Anyway, it is indeed interesting that you "solved the issue" by adding a
new protocol instead.

> The way Squeak currently implements #respondsTo: and #canUnderstand:
> is compatible with the way other Smalltalks do it.
> 
> To be sure, the operations have misleading names.  If it were a matter
> of designing a new language, they'd be good names to avoid.  To be sure,
> there is a fair bit of broken code that uses #respondsTo: when it
> should not.  But the best response is to fix that code, not change the
> semantics of a basic operation.
> 
> 	I decided that this is the right way because it is the semantics that is
> 	expected by the vast majority of senders in the system.
> 
> There are 112 senders of #respondsTo: in Squeak 3.6g2; if it is true that
> "(the human authors of) the vast majority of senders (of #respondsTo:) in
> the system" didn't understand the semantics of a basic operation which is
> described extremely clearly in several classic textbooks, this is extremely

> worrying.  But still, adopting (and correcting, if necessary) the
> #honestlyRespondsTo: solution and fixing the broken code seems better than
> changing the semantics of a basic operation.

I tend to agree I think, perhaps the word "honestly" can be up for
discussion - but that is a small detail.

> 	close
> 		"close if you can"
> 		(stream respondsTo: #close) ifTrue: [
> 				stream closed ifFalse: [stream close]]
> 	
> 	This method uses the message #respondsTo: (which is essentially the same
> 	as #canUnderstand:) in order to know whether the class of 'stream'
> 	acually offers the functionality #close and not whether the class of
> 	'stream' declares an abstract or disabled method #close!
> 	
> Well, any code that passes in an object where an operation required by
> the receiver is abstract *DESERVES* to break; in fact ought to break as
> loudly and as early as possible.

This I *really* agree on.

[SNIP of reinforcement of that point]
> 	This is really problematic because especially declaring a method as
> 	abstract is an extremely important concept of OO programming and it is
> 	therefore not acceptable that Smalltalk does not offer a programmer to
> 	do so without breaking the system.
> 	
> I agree 100% that abstract classes and abstract methods are important
> OO concepts.  I expect anyone who uses them to have made an honest attempt
> to understand them.  A class which has at least one abstract method is an
> abstract class.  And one of the basic rules about abstract classes is
> DON'T CREATE INSTANCES OF ABSTRACT CLASSES.
> 
> If you think you have an application where this makes sense, what _really_
> makes sense (at least in Smalltalk) is to create an application-specific
> subclass of the abstract class where you have made your mind up about
> which operations will be supported and how.
> 
> The real problem here is that Squeak doesn't actually _know_ when a class
> is abstract, and doesn't notice when you create an instance of one.

Interesting conclusion.

> Now, I do agree that if a class defines a selector by self shouldNotImplement    
> then an instance of (a concrete subclass of) that class should not be regarded
> as responding to the selector in question.  That's why I wrote
> #honestlyRespondsTo:.  A class where you *have* made a conscious decision
> "No I do not support this method" is different form a class where you have
> decided not to decide yet.

Sounds very true.

> 	I don't know. If they do it the same way as it has been done in Squeak,
> 
> Modulo implementation details, they do.
> 
> 	it is more than likely that also in these dialects, the semantics of
> 	#canUnderstand: and #respondsTo: does not correpsond to what is expected
> 	in practically all the users of these methods.
> 
> Quite likely.  This is why the better Smalltalk textbooks say "don't use
> #respondsTo:, it doesn't do what you think it does."  The _real_ best thing
> to do to Squeak is probably not to butcher #respondsTo: but to redesign
> much of the code that uses it.

And perhaps even rewrite the comment of that method to warn against its
use!
And even enhance Lint to catch "offenders". Hey, perhaps it already
does. :)

> And of course the Lint checking part of RB should offer a warning about
> uses of #respondsTo:/#canUnderstand:.  Maybe it does; I haven't checked.

Duh, two minds, one thought.

> 	As a consequence, I assume that also these dialects do not allow
> 	a programmer to declare methods that should be implemented in
> 	subclasses as 'subclassResponsibility' without breaking other code.
> 	
> I can't make sense of that.  They are just like Smalltalk:  you can define
> any method you want to be self subclassResponsibility, but if you do that,
> you then have an obligation NEVER TO CREATE A DIRECT INSTANCE OF SUCH A CLASS.
> 	
> 	Our goal is to have a kernel that allows a programmer to explicitly
> 	declare methods that should be implemented in a subclasses (i.e.,
> 	abstract methods) and methods that are not appropriate for a certain
> 	class without crashing the whole image.
> 	
> We have that already.  The problem is not *declaring* methods that should
> be implemented in subclasses, it is *creating direct instances of abstract
> classes*.  The fix that is needed is some way for the system to know that
> a class is an abstract class and for it to forbid attempts to directly
> instantiate such classes.

Yes, sounds reasonable.

[BIG SNIP of more reasoning]
> In my (still unfinished, probably never to be finished) Smalltalk compiler,
> I created new messages abstractSubclass:... for declaring abstract classes,
> and didn't allow "self subclassResponsibility" in concrete classes.  One
> reason was the dispatch method I was using; numbering only the concrete
> classes helped.  But I certainly found it helpful to mark the distinction:
> it simplified my code.  Squeak could tell abstract classes from concrete
> classes without ceasing to be dynamic; it could be as simple as having a
> "number of subclassResponsibility methods" variable in a class.

Interesting.

regards, Göran



More information about the Squeak-dev mailing list