Object-Oriented Techniques

Instanciation

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.a

will 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.

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.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License