Reputation: 4819
If I got it right so an Abstract Class is one which has at least one abstract method?
Now, if it's abstract so I am supposed to be unable to make instances of that Class?
Like, said Abst
is a name of an abstract class (because it contains an abstract method) so doing:
a := Abst new.
is illegal and should pop-up an error/exception? or the problem should arise here:
a := Abst class new.
?
UPDATE: As suggested, I have made the next method which won't let the user to make instances of a Class but it doesn't work:
makeAbstract: aClass
aClass compile: 'new
^ self subclassResponsibility'.
Upvotes: 3
Views: 5246
Reputation: 3200
The (fixed) "new-blocker" introduces a slight inconvenience for its concrete subclasses: they will have to redefine new, and cannot make use of any inherited superclasses' new functionality. You can get around this with a little guard which checks if it is really the abstract class that is tried to be instantiated:
AbstractClass class >> new
self == AbstractClass ifTrue:[
^ self abstractClassInstantiationError
].
^ super new
(notice the identity-compare here, which works even if you have stacked multiple abstract classes on top of each other)
Upvotes: 2
Reputation: 6390
Welcome to Smalltalk! One of the great things about Smalltalk is that it trusts developers, who benefit from the power that comes with that trust. So words like "unable to" and "illegal" rarely apply.
Like most other things, Abstract classes in Smalltalk are more like a suggestion/pointer than a rigid law. The two clues you look for are #subclassResponsibility and #shouldNotImplement. These two methods are clues to subclassers whether or not to include a particular method. Check senders for examples in the image (always a great starting point for questions).
Since "abstract", as described above, is really on a per-method basis, your examples would not generate an error (unless #subclassResponsibility or #shouldNotImplement is called from initialize.
Two small things:
UPDATE: if you want to signal to users of your class that they should not create instances (like in your comment below), you could write:
Abstract>>new
^ self subclassResponsibility.
Then "Abstract new" -> error, but "AbstractSubclass new" is okay.
Although there is still no guarantee that AbstractSubclass has overridden the abstract method (not #new, but the one that caused you to want to prevent instancing in the first place), in practice this will not be a problem. If you really wanted to, you could put a check, maybe in #initialize, that makes sure none of the instance's methods call #subclassResponsibility, but don't bother unless you have good reason.
UPDATE 2: Your utility method to make a class abstract would be:
Class>>makeAbstract
self class compile: 'new
^ self subclassResponsibility'.
Upvotes: 11
Reputation: 661
I recommend you to read the Pharo By Example book. You can find it here: http://pharobyexample.org/ and you will find a lot of interesting stuff. It is an open book, free, and you can download the pdf. In fact, what you are asking is explained in chapter 5, page 88.
Upvotes: 2
Reputation: 39414
Yes, an abstract class should have at least one abstract method, but no, you can still make instances of that class.
What you should do is make concrete classes which inherit from the abstract class which you can make instances of and call methods on.
Abstract methods in Smalltalk have a particular implementation which make them and the class abstract:
method
self subclassResponsibility
This also means that subclasses should override this method and provide a concrete implementation.
If you see an error regarding subclassResponsibility your code has either called a method on the abstract class, or your subclass has not provided an implementation for the method.
Upvotes: 3
Reputation: 15917
In Smalltalk you can just instantiate abstract classes. As long as you do not call abstract methods it just works. You might want to implement missing methods at runtime.
Upvotes: 3