Instantiation
Magik does not have ‘class’ objects. Instead of that you define an exemplar of the class .e.g. with the define_record_exemplar procedure:
define_slotted_exemplar(:my_class,
{{:my_slot1,_unset},
{:my_slot2,_unset}},
{:my_parent_class,:my_mixin})
$There is no technical difference between this exemplar and all other instances of that class. So you may use the exemplar directly as an instance of the class. In fact in most cases you should avoid that, except for classes following the singleton pattern (like gis_program_manager, ds_environment, smallworld_product,…). For other classes there should be something like a new() method, which returns an initialised clone of the exemplar, for example:
_method my_class.new(arg1,arg2)
>> _clone.init(arg1,arg2)
_endmethod
$
_private _method my_class.init(arg1,arg2)
.my_slot1 << arg1
.my_slot2 << arg2
>> _self
_endmethod
$In this (usual) implementation the init() method initiates the slots. The new() method calls this init() method on the clone, leaving the slots of the exemplar unchanged.
Conflict Methods
If you define my_method() on the classes or mixins a and b, and you have a third class c inheriting from a and b, a conflict method on c is generated automatically.
_method a.my_method()
# do something
_endmethod
$
_method b.my_method()
# do something else
_endmethod
$
def_slotted_exemplar(:c,{},{:a,:b})
$Calling my_method() on c will raise an error condition unless you implement my_method() on c as well. A typical implementation for such a conflict resolution would be:
_method c.my_method()
## conflict resolution
_super(a).my_method()
_super(b).my_method()
_endmethod
$Abstract Methods
You implement some functionality on a mixin (or a slotted_exemplar), intended to be used by a subclass. It may happen, that in your code there are some calls to methods, which have to be implemented on the actual child class using your funcitionality, but it makes no sense to implement them on your mixin/slotted_exemplar. In this case you may implement them as _abstract. This gives you the possibility to give them a _pragma-Statement and a public comment, describing what that method should do. For example
_abstract _method my_class.my_method
## whatever this method should do...
_endmethod
$Execpt for the conflict behaviour this implementation is equivalent to the following code
_method my_class.my_method
## whatever this method should do...
condition.raise(:subclass_should_implement,
:name,:my_method,
:class,_self.class_name)
_endmethod
$Note that _self.class_name normally is not :my_class, but is the class name of the object my_method is called on during runtime (normally a child class of :my_class).
In fact there is no technical need to implement abstract methods. But if you get used implementing them, you have a formal desciption of the implementation needs of child classes. And in case you have forgotten the implementation of the method on the child class, the raised condition :subclass_should_implement together with the public comment of your abstract method normally gives you a better hint for fixing a bug like that, than the condition :does_not_understand, which would have been raised otherwise.
Abstract Methods don't conflict (since version 4.1(1))
Think of the following scenario: You have an abstract method defined on one class, another class implementing the method, and third class inheriting from from both classes:
def_mixin(:my_mixin)
$
_abstract _method my_mixin.a
_endmethod
$
def_slotted_exemplar(:my_base_class,{},{})
$
_method my_base_class.a
>> :my_return_value
_endmethod
$
def_slotted_exemplar(:my_child_class,{},{:my_base_class,:my_mixin})
$Since version 4.1(1) the compiler automatically resolves the conflict method on my_child_class for the non abstract implementation, so in the example the call
my_child_class.awill just return :my_return_value. In fact this is a feature making the concept of abstract methods much more valuable, as you otherwise might be faced with writing many conflict solving methods.
Subclassing by an abstract method to prevent conflict methods
(Tested with SW 5.3.2)
You may also subclass a non abstract method with an abstract method. This can be useful, if you include a product, which defines a mixin, from which you want to make inherit many of your classes, but there are some methods defined on the mixin, you want to use in no case and - even worse - which are already defined whithin your class hierarchy.
I give an example. In my code I have defined:
def_slotted_exemplar(:my_parent)
$
_method my_parent.a_method()
## my implementaion of a_method()
# do something
_endmethod
$
def_slotted_exemplar(:my_child)
$Now the product to be included defines a mixin with another implementation of a_method():
def_mixin(:their_mixin)
$
_method their_mixin.a_method()
## their implementation of a_method()
# do something else
_endmethod
$
_method their_mixin.another_method()
# do another thing
_endmethod
$Now I want to use the functionality of another_method() on my_child but I'm not interested in their implementaion of a_method()
Solution without abstract methods
The first idea would be to write:
their_mixin.add_child(my_child)with the consequence that I have to write a conflict resolution method a_method() on my_child:
_method my_child.a_method()
## conflict resolution
## only implementation of my_parent should be used
_return super(my_parent).a_method()
_endmethodIf I have many child classes in a similar way, this could by quite annoying.
Solution with abstract methods
In this case the following implementation could be more elegant:
def_mixin(:my_variant_of_their_mixin,{their_mixin})
$
_abstract _method my_variant_of_their_mixin.a_method()
## preventing their_mixin.a_method() from conficting
_endmethod
$
my_variant_of_their_mixin.add_child(my_child)
$Instead of having to write many conflict resolution methods as ther other solution, now I have to write only one abstract method.
Comparision with other languages
Abstract methods within magik are very similar to what is called pure virtual function in other languages. In contrast to such a pure virtual function, the definition of an abstract method on a magik class does not hinder this class to be used / instanciated.





