Search code examples
eiffel

Eiffel: Creator instruction applies to target of a deferred type


Class A

deferred Class A

feature -- 

    item: X -- X is deferred

    set_item_for_some_reason (param: N)
        do
            create item.make_from_param (param)
        end

end -- class

Class B

Class B inherit

    A

feature -- 

    item: Y -- Y not deferred inherits from X

end -- class

I'd like to create in the same class an attribute which will be defined in the descendent and get a Creator instruction applies to target of a deferred type Error which makes sens in a way of reduced context, but not in the context I intend it to do it.

For me it does make sense to be able to create an object in current deferred class, I wont have to implement in all the descendants! which will be a wrong design... something like this:

deferred Class A

feature -- 

    item: X -- X is deferred

    set_item_for_some_reason (param: N)
        do
            set_item_from_param (param)
        end

    set_item_from_param (param: N)
        deferred
        end

end -- class


Class B inherit

    A

feature -- 

    item: Y -- Y not deferred


    set_item_from_param(param: N)
        do
            create item.make_from_param (param)
        end

end -- class

Am I wrong with my design or is it a restriction which is still discussed about Eiffel compiler as I understood? and if yes, what would be the best practice workaround?


Solution

  • A possible solution is to use generic classes. In the class A, the formal generic parameter has a creation constraint that the corresponding actual generic parameter should have a particular creation procedure:

    class A [G -> X create make_from_param end] feature
        item: detachable G
        set_item_for_some_reason (param: N)
            do
                create item.make_from_param (param)
            end
    end
    

    A descendant class can specify an actual generic that has this creation procedure:

    class B inherit
        A [Y]
    end
    

    To make sure we are on the same page, here is the code of classes X and Y:

    deferred class X feature
        make_from_param (param: N)
            deferred
            end
    end
    
    class Y inherit
        X
    create
        make_from_param
    feature
        make_from_param (param: N)
            do
            end
    end
    

    You can add as many such descendants as you wish. The main restriction is that whenever class A is used, its actual generic parameter should have the specified feature as a creation one. For example, it's OK to declare a type A [Y]. But A [X] would trigger an error.

    If in a descendant, the type of item should not be fixed yet, it's possible to propagate it, repeating the constraint on the formal generic:

    class C [G -> X create make_from_param end] inherit
        A [G]
    end