[Pharo-project] Abstract classes
Dear List, I was looking for a way to test whether a class is abstract or not. One easy way, is to check whether the class sends the message subclassResponsibility. This is not perfect, since we should also check whether the receiver is 'self' and this is the only statement in the method body. Looking at sender of #subclassResponsibiliy did not reveal anything. I propose to define the following method: Behavior>>isAbstract ^ self methods anySatisfy: [:cm | cm sendsSelector: #subclassResponsibility ] Shall I can create an issue and add a changeset? Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
On Wed, Oct 28, 2009 at 10:22 AM, Alexandre Bergel <alexandre@bergel.eu>wrote:
Dear List,
I was looking for a way to test whether a class is abstract or not. One easy way, is to check whether the class sends the message subclassResponsibility. This is not perfect, since we should also check whether the receiver is 'self' and this is the only statement in the method body. Looking at sender of #subclassResponsibiliy did not reveal anything. I propose to define the following method:
Behavior>>isAbstract ^ self methods anySatisfy: [:cm | cm sendsSelector: #subclassResponsibility ]
The only problem I see (maybe I am wrong) here is that there are already a lot of implementors of isAbstract. For example, those used in Sunit. So, if you add this method to Behavior, there will be a lot of non-intentional overrides.
Shall I can create an issue and add a changeset?
Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
The only problem I see (maybe I am wrong) here is that there are already a lot of implementors of isAbstract. For example, those used in Sunit. So, if you add this method to Behavior, there will be a lot of non-intentional overrides.
I thought about it, but I haven't felt this could be a real problem. Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
The only problem I see (maybe I am wrong) here is that there are already a lot of implementors of isAbstract. For example, those used in Sunit. So, if you add this method to Behavior, there will be a lot of non-intentional overrides.
As Mariano writes, most applications implement a message #isAbstract themselves with the exact semantics they require. I don't think a generic message in Behavior is really useful, especially if it is not used by the core system. Interesting in this context is how the Refactoring Engine determines if a class is abstract: "Smalltalk doesn't have any language feature that denotes an abstract class like C++ or Java. As a result, we check for a couple things when looking for an abstract class. If the class contains any method that sends #subclassResponsibility, the we consider the class as abstract. A method that sends subclassResponsibility signifies that users should override this method in every subclass to have all the class' functionality to work. Another check we use to determine if a class is abstract is to look for references to the class. If the class is not referenced then the class is considered to be abstract, since there is no way to create an instance of the class." [http://st-www.cs.illinois.edu/users/brant/Refactory/] Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch
As Mariano writes, most applications implement a message #isAbstract themselves with the exact semantics they require. I don't think a generic message in Behavior is really useful, especially if it is not used by the core system.
In that case, we could have isAbstractClass or something else. I feel this information is important.
If the class contains any method that sends #subclassResponsibility, the we consider the class as abstract.
I am not sure what "contains" means in that context. But apparently, the definition you gave is not sufficient. The presence of subclassResponsibility need to be checked in the methods obtained from superclasses. (the code I gave in my previous email does not satisfy this although). I will create an issue. Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
If the class contains any method that sends #subclassResponsibility, the we consider the class as abstract.
Presence of abstract method in the metaclass is also necessary. -=-=-=-=-=-=-=-=-=-=-=-= ISSUE #1383: This issue proposes the addition of -two new methods in Behavior: allMethods and isAbstractClass. -one new method in Metaclass -two testing methods in BehaviorTest that test the allMethods and isAbstractClass allMethods returns the list of non-overrided compiled methods. Behavior already answer to allSelectors, allMethods was missing. isAbstractClass answers true if the receiving class or its metaclass contains or inherits an abstract method All tests in BehaviorTest are green. Tested in a pharo1.0-10491- rc1dev09.10.5 -=-=-=-=-=-=-=-=-=-=-=-= A .cs file is attached to the issue. Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
As Mariano writes, most applications implement a message #isAbstract themselves with the exact semantics they require. I don't think a generic message in Behavior is really useful, especially if it is not used by the core system.
In that case, we could have isAbstractClass or something else. I feel this information is important.
What would be your isAbstract be useful for? - SUnit will still have to implement its own #isAbstract to decide if a class should be runnable or just provide test templates. - Pier will still have to implement its own #isAbstract to decide if a class should show up in the GUI. - Magritte will still have to implement its own #isAbstract to decide if an arbitrary class can be instantiated from the GUI. - ...
 If the class contains any method that sends #subclassResponsibility, the we consider the class as abstract.
I am not sure what "contains" means in that context. But apparently, the definition you gave is not sufficient. The presence of subclassResponsibility need to be checked in the methods obtained from superclasses. (the code I gave in my previous email does not satisfy this although).
contains = (I assume) in the set of understood selectors (that includes superclasses) Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch
What would be your isAbstract be useful for?
To know whether it is wise to instantiate a class or not Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
What would be your isAbstract be useful for?
To know whether it is wise to instantiate a class or not
That would be a pure guess then. Presumably you will still have to look at the implementation, at the documentation, at its users or study the coding conventions of the project to know for sure what to do with the thing. Lukas -- Lukas Renggli http://www.lukas-renggli.ch
Em 28/10/2009 17:52, Lukas Renggli <renggli@gmail.com> escreveu:
What would be your isAbstract be useful for? To know whether it is wise to instantiate a class or not
That would be a pure guess then. Presumably you will still have to look at the implementation, at the documentation, at its users or study the coding conventions of the project to know for sure what to do with the thing.
Yes. Thinking aloud: if we want to insure a class shall not be instantiated, shouldn't we put an error in #new of that class?
2009/10/28 <csrabak@bol.com.br>:
Em 28/10/2009 17:52, Lukas Renggli <renggli@gmail.com> escreveu:
What would be your isAbstract be useful for? To know whether it is wise to instantiate a class or not
That would be a pure guess  then. Presumably you will still have to look at  the implementation, at  the documentation, at its  users or study the coding conventions of the project to know for sure what to do with the thing.
Yes.
Thinking aloud: if we want to insure a class shall not be instantiated, shouldn't we put an error in #new of that class?
That would be the shortest way to freeze you image: Object>>#freezeMyImage ^self subclassResponsibility ...and you could not create any instance of Object and its subclasses anymore (but via a few primitives bypassing this mechanism). Beside, do you want a runtime check at each creation ? We would have to cache the information at least... Nicolas
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Em 29/10/2009 08:36, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> escreveu:
2009/10/28 <csrabak@bol.com.br>:
Em 28/10/2009 17:52, Lukas Renggli <renggli@gmail.com> escreveu:
What would be your isAbstract be useful for? To know whether it is wise to instantiate a class or not
That would be a pure guess then. Presumably you will still have to look at the implementation, at the documentation, at its users or study the coding conventions of the project to know for sure what to do with the thing. Yes. Thinking aloud: if we want to insure a class shall not be instantiated, shouldn't we put an error in #new of that class? That would be the shortest way to freeze you image: Object>>#freezeMyImage ^self subclassResponsibility
That was not the way I envisaged. . . see below.
...and you could not create any instance of Object and its subclasses anymore (but via a few primitives bypassing this mechanism).
Again what I was thinking aloud (and continuing) is less of putting some 'magical' method in Object that detects if it's abstract or not but a reasonable way of the programmer when constructing the class put int in the code: Say we had: Object>>isAbstract ^false When a class is added to the system the one would do: SomeClass class>>new ^self raise: Error. SomeClass>>isAbstract ^true
Beside, do you want a runtime check at each creation? We would have to cache the information at least...
I don't any use of the mechanism if it is not enforceable automatically. Otherwise, I could cynically say that the easiest way to attain the objective would have the programmer inspect the class code [s]he is thinking of instantiating! OTOH, notice that mainstream languages use explicit declarations to have its classes Abstract, not the way around (I mean having the programming environment detect using its characteristics). my 0.01999999.... -- Cesar Rabak
2009/10/29 <csrabak@bol.com.br>:
Em 29/10/2009 08:36, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> escreveu:
2009/10/28 <csrabak@bol.com.br>:
Em 28/10/2009 17:52, Lukas Renggli <renggli@gmail.com> escreveu:
What would be your isAbstract  be useful for?  To know whether it is wise to instantiate a class or not
That would be  a pure guess then. Presumably  you will still have to look at the implementation, at the documentation, at its users or study the  coding conventions of the project  to know for sure what to do with the thing. Yes. Thinking  aloud:  if  we want  to  insure  a  class shall  not  be instantiated, shouldn't we put an error in #new of that class?  That  would  be  the  shortest  way  to  freeze  you  image:  Object>>#freezeMyImage  ^self subclassResponsibility
That was not the way I envisaged. . . see below.
Yes, sorry my message was not clear. I extrapolated, using Alexandre technique for the goal you exposed (restricting #new). Of course that does not apply to your aloud thinking. Nicolas
 ...and  you  could  not  create  any instance  of  Object  and  its  subclasses  anymore  (but  via  a  few  primitives  bypassing  this  mechanism).
Again what I was thinking aloud (and continuing) is less of putting some 'magical' method in Object that detects if it's abstract or not but a reasonable way of the programmer when constructing the class put int in the code:
Say we had:
Object>>isAbstract  ^false
When a class is added to the system the one would do:
SomeClass class>>new  ^self raise: Error.
SomeClass>>isAbstract  ^true
 Beside, do  you want a runtime  check at each creation?  We would  have to cache the information at least...
I don't any use of the mechanism if it is not enforceable automatically.
Otherwise, I could cynically say that the easiest way to attain the objective would have the programmer inspect the class code [s]he is thinking of instantiating!
OTOH, notice that mainstream languages use explicit declarations to have its classes Abstract, not the way around (I mean having the programming environment detect using its characteristics).
my 0.01999999....
-- Cesar Rabak
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Lukas I'm not that against the idea proposed by alex. I think that knowing that a class is abstract is important to have and this is not because Smalltalk original language was weak that we could not define now a clear definition. I do not like the definition of RB people because I have class that are not abstract and that are not referenced because I just did not load the package that use them. Now if magritte needed to know that a class should show up in a UI then may be it should be called differently because an abstract class is clearly a class that we should/cannot instantiate. If you take ***any*** book on OOP this is a basic concept. Stef On Oct 28, 2009, at 8:52 PM, Lukas Renggli wrote:
What would be your isAbstract be useful for?
To know whether it is wise to instantiate a class or not
That would be a pure guess then. Presumably you will still have to look at the implementation, at the documentation, at its users or study the coding conventions of the project to know for sure what to do with the thing.
Lukas
-- Lukas Renggli http://www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
I'm not that against the idea proposed by alex.
I am not against it either.
I think that knowing that a class is abstract is important to have and this is not because Smalltalk original language was weak that we could not define now a clear definition.
My complaint is more against: - Why is it useful, if the information is a pure guess and depends on what the author thinks is abstract? - Why should it be added to the core, if it is not used by anything it the core? Who would be using it?
I do not like the definition of RB people because I have class that are not abstract and that are not referenced because I just did not load the package that use them.
True, but the definition of Alex is no better. He made up an implementation that is useful in one of his contexts, but it certainly isn't applicable everywhere. Also there might be people that consider classes that send #requirement, #explicitRequirement, or #shouldBeImplemented as abstract. Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch
2009/10/28 Alexandre Bergel <alexandre@bergel.eu>:
What would be your isAbstract be useful for?
To know whether it is wise to instantiate a class or not
Alexandre
I often instantiate Object marker := Object new. Nicolas
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel  http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Object does not "contain" any abstract method. Alexandre On 29 Oct 2009, at 05:31, Nicolas Cellier wrote:
2009/10/28 Alexandre Bergel <alexandre@bergel.eu>:
What would be your isAbstract be useful for?
To know whether it is wise to instantiate a class or not
Alexandre
I often instantiate Object
marker := Object new.
Nicolas
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
Lukas Renggli <renggli@...> writes:
In that case, we could have isAbstractClass or something else. I feel this information is important.
What would be your isAbstract be useful for?
- SUnit will still have to implement its own #isAbstract to decide if a class should be runnable or just provide test templates. - Pier will still have to implement its own #isAbstract to decide if a class should show up in the GUI. - Magritte will still have to implement its own #isAbstract to decide if an arbitrary class can be instantiated from the GUI. - ...
Looks to me like these are application specific definitions of abstractness. Why not name them #isAbstractTest, #isAbstractComponent et cetera? While in the same time, there is a system-wide notion of abstract classes for which the generic #isAbstract should be reserver. NB, I am making this injection in the hope to disentangle to issue of method naming from the issue of the exact implementation of a general #isAbstract method (on which I agree with Lukas that it should be chosen carefully). cheers, AA
- SUnit will still have to implement its own #isAbstract to decide if a class should be runnable or just provide test templates. - Pier will still have to implement its own #isAbstract to decide if a class should show up in the GUI. - Magritte will still have to implement its own #isAbstract to decide if an arbitrary class can be instantiated from the GUI. - ...
NB, I am making this injection in the hope to disentangle to issue of method naming from the issue of the exact implementation of a general #isAbstract method (on which I agree with Lukas that it should be chosen carefully).
For now, I used #isAbstractClass Cheers, Alexandre -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
participants (7)
-
Adrian Kuhn -
Alexandre Bergel -
csrabak@bol.com.br -
Lukas Renggli -
Mariano Martinez Peck -
Nicolas Cellier -
Stéphane Ducasse