repeated inheritence of same class

40 views
Skip to first unread message

Gachoud Philippe

unread,
Jun 25, 2019, 2:00:28 PM6/25/19
to Eiffel Users
Hi all, sure this topic was already discussed, but could not find a quick and good answer to that. I think code talks better to our ears, but ....

The semantic for me is to have the same semantic for a method that returns a DB constraint and could have some ensures and contract.... in this case not, but I stick to the concept ;-)

The compiler seems to disagree with me as I have to select one, but I dont want :D

Am I wrong like the compiler says, or like I'm doing things?

Thx in advance!

Error code: VMRC(2)

Error: conflict between versions of a repeatedly inherited feature.
What to do: list one of the versions in exactly one Select clause.

Class: PK_DB_ENTITY
In current class: primary_key_constraint: CONSTRAINT
In current class: primary_key_constraint_join: CONSTRAINT



Code

deferred class
    CONSTRAINTABLE

feature
-- Status report

    constraint
: CONSTRAINT
        deferred
       
end

end



class
    PK_DB_ENTITY

inherit
    DB_ENTITY
        redefine
            set_random_for_update
,
            set_random_for_insert
,
            fields_mapping
,
            set_from_db_service
,
            valid_for_insert
,
            valid_for_delete
,
            valid_for_update
       
end

    CONSTRAINTABLE
        rename
            constraint
as primary_key_constraint
        undefine
            default_create
,
           
out
       
end

    CONSTRAINTABLE
        rename
            constraint
as primary_key_constraint_join
        undefine
            default_create
,
           
out
       
end



feature
-- Status report

    primary_key_constraint
: CONSTRAINT
       
require else
            valid_primary_key
(primary_key)
       
do
            create
{FIELD_CONSTRAINT} Result.make (table_name, Primary_key_db_column_name, {CONSTRAINT}.Equal_operator, primary_key.out)
       
end

    primary_key_constraint_join
: CONSTRAINT
       
require else
            valid_primary_key
(primary_key)
       
do
            create
{FIELD_CONSTRAINT} Result.make (table_name + "_join", Primary_key_db_column_name, {CONSTRAINT}.Equal_operator, primary_key.out)
       
end


Larry Rix

unread,
Jun 25, 2019, 2:23:45 PM6/25/19
to Eiffel Users
Take careful note of the error text ... it tells you what to do. Use the "Select clause" in the inheritance part of the class to tell the Eiffel compiler from where to "select" the version of the routine you want in the Current class.

Note that between where you created the ancestor and the point where you are inheriting, you may have changed (redefined) the nature of the inherited feature. This is especially true of deferred features, which can have differing implementations in downstream descendants. When you then choose to inherit the same root class ancestor through two differing lines of lineage, YOU must decide (not the compiler) which version of the feature applies to your Current class. Now—they answer may be that it is none-of-the-above and you need to provide a new implementation in your Current class.

Gary Smithrud

unread,
Jun 25, 2019, 2:35:26 PM6/25/19
to eiffel...@googlegroups.com
The compiler is correct.  When you use a feature with the CONSTRAINT type and you call constraint, which one will be used?  This is the purpose of select.  With multiple inheritence, you can set an instance of your class to a variable/feature results of type DB_ENTITY or CONSTRAINT or any superclass in the hierarchy.

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/eiffel-users/dae6b1c9-09f0-483f-8256-26b71a549adb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gachoud Philippe

unread,
Jun 25, 2019, 3:54:22 PM6/25/19
to eiffel...@googlegroups.com
thx for your explanations but still are fuzzy for me... how can I reach my goal of having 2 features with 2 different implementation into same class with 2 times inheritence from CONSTRAINED? Still dont got it sry...

--
**********************************************
Philippe Gachoud
Puerto Williams 6657
Las Condes
Santiago de Chile
+56  934022210
ph.ga...@gmail.com
**********************************************
   

Gary Smithrud

unread,
Jun 25, 2019, 4:03:52 PM6/25/19
to eiffel...@googlegroups.com
Which one do you want as default?  Personally, I do not think that it matters which you choose, since it is likely that you will be only using this class through the DB_ENTITY hierarchy.

r...@amalasoft.com

unread,
Jun 25, 2019, 4:29:52 PM6/25/19
to eiffel...@googlegroups.com
Hi Philippe

These might help, a little.  The document form ("Adapting ...") is rather old, and there have been language changes in the last decade :)  But, the concepts are still there.  The presentation form ("Re-What...") is much fresher (and a whole lot shorter)
R
Re-What - prt.pdf
Adapting_Inherited_Features_in_Eiffel-lores.pdf

Gachoud Philippe

unread,
Jun 25, 2019, 9:01:40 PM6/25/19
to eiffel...@googlegroups.com
I'd like both methods with 2 different implementation renamed as shown by 

primary_key_constraint: CONSTRAINT
        
require else
            valid_primary_key 
(primary_key)
        
do
            create 
{FIELD_CONSTRAINT} Result.make (table_name, Primary_key_db_column_name, {CONSTRAINT}.Equal_operator, primary_key.out)
        
end

    primary_key_constraint_join
: CONSTRAINT
        
require else
            valid_primary_key 
(primary_key)
        
do
            create 
{FIELD_CONSTRAINT} Result.make (table_name + "_join", Primary_key_db_column_name, {CONSTRAINT}.Equal_operator, primary_key.out)
        
end

Gachoud Philippe

unread,
Jun 25, 2019, 9:25:08 PM6/25/19
to eiffel...@googlegroups.com
thx it would have been nice to have this doc for me at the beginning of my tripulations with multiple inheritence! but as I remember (but not where into the library) there are cases of direct repeated inheritence where B inherits 2 times from A into the same class. @ this time it was difficult for me to imagine a concrete case till I encountered the one I presented you in the code below/above. 
Hope you understand in other words that I'd like to have 2 features with different names but inherited both from the same A (CONSTRAINED) class with "same" semantic and signature, but different name and implementation. 
- One time (not once to avoid confusion ;-)) primary_key_constraint
- One time primary_key_constraint_join

maybe I'm repeating my point unable to get yours....

Thx for your precious help 

Gachoud Philippe

unread,
Jun 25, 2019, 9:28:57 PM6/25/19
to eiffel...@googlegroups.com
this case is the one I want and there could ve more methods implementing a "to_constraint_as_..." which I prefered trying to stick to eiffel nomenclature as I wrote. Any suggestion is in all case mostly welcome
Screenshot_20190625-211450_Adobe Acrobat.jpg

Alexander Kogtenkov

unread,
Jun 26, 2019, 2:50:16 AM6/26/19
to eiffel...@googlegroups.com
The select clause specifies which version should be used when making a call

    c.constraint

when c is declared with type CONSTRAINTABLE at compile time, but is attached to an object of type PK_DB_ENTITY at run-time. As currently written, class PK_DB_ENTITY has two versions of the feature, and it's unclear which one should be called. This is why the code does not compile.

The select clause is not required to make calls

   e.primary_key_constraint
   e.primary_key_constraint_join

when e is declared with type PK_DB_ENTITY: both features can be used without any restriction even when one of the features is selected to resolve the ambiguity mentioned above.

Hope this helps,
Alexander Kogtenkov


Gachoud Philippe <ph.ga...@gmail.com>:

CONSTRAINTABLE

Anthony W

unread,
Jun 26, 2019, 4:27:25 AM6/26/19
to eiffel...@googlegroups.com
My installed version of Eiffel (17.05) is horked, and so while I was able to compile the following code without error, I couldn't test it to see the results. Hopefully it can get you a bit closer to what you are trying to accomplish.

class
PK_DB_ENTITY

inherit
CONSTRAINTABLE
rename
constraint as primary_key_constraint
select
primary_key_constraint
end

CONSTRAINTABLE
rename
constraint as primary_key_constraint_join
end


My apologies if I'm only increasing the noise levels - it's been ages since I've worked with Eiffel, but this question piqued my curiosity and wouldn't stop itching at my brain.

@ Roger Osmond - thank you for the .pdf's. The second one is an AMAZING write up!

Regards,
Anthony

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.

Larry Rix

unread,
Jun 26, 2019, 8:44:43 AM6/26/19
to Eiffel Users
There is another solution that does NOT involve inheritance.

If both of the ancestor classes are not deferred (but implemented), then one can do the following:

  1. create two features—one for each class.
    • You can place these in their own feature group and export them to {NONE} if you like.
  2. Ensure that both features are initialized (properly created)
  3. In another feature group that is exported
    • Create a wrapper feature for each feature on each class that you want to access.
We have always referred to this as doing a "Has-a" model instead of an "Is-a" model.

Doing the "Has-a" form spares you the grief of having to coordinate inheritance with the compiler. This is especially true if you actually want feature from both classes, but those features have new and different versions.

By taking inheritance out of the picture, you've greatly simplified matters and you've actually opened up possibilities that you did not have by using inheritance.



Gachoud Philippe

unread,
Jun 27, 2019, 5:15:40 PM6/27/19
to Eiffel Users
Antony gave me the answer I was looking for I think

class
PK_DB_ENTITY

inherit
CONSTRAINTABLE
rename
constraint as primary_key_constraint
select
primary_key_constraint
end

CONSTRAINTABLE
rename
constraint as primary_key_constraint_join
end

But for me in the semantic, why do I have to select one of 2 inherited features if it has been renamed?

Thx to all

Gary Smithrud

unread,
Jun 27, 2019, 7:15:54 PM6/27/19
to eiffel...@googlegroups.com
Sorry, did not know that you needed to know how to use select.

Here is why:select is needed: 

foo
local
   my_entity: PK_DB_ENTITY
   my_constraint: CONSTRAINTABLE
do
   create my_entity.make
   my_constraint := my_entity
   if my_constraint.constraint = my_entity.primary_key_constraint then
      -- Is this true?
   elseif my_constraint.constraint = my_entity.primary_key_constraint_row then
      -- or is this true?
   end
end

This is the purpose of select.  You need to decide which if statement is true.  You can not call my_constraint.primary_key_constraint directly.  Note...I don't remember the class, so you probably can't use '=', but I was just being lazy.

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.

Finnian Reilly

unread,
Jun 28, 2019, 11:15:47 AM6/28/19
to Eiffel Users


But for me in the semantic, why do I have to select one of 2 inherited features if it has been renamed?


This code should make it clear
 
test
   
local
      db
: PK_DB_ENTITY
      constraintable
: CONSTRAINTABLE
      constraint
: CONSTRAINT
   
do
      create db
.make
      constraintable
:= db
      constraint
:= constraintable.constraint -- result depends on which constraint was selected
   
end

 

Gachoud Philippe

unread,
Jun 28, 2019, 11:45:13 AM6/28/19
to eiffel...@googlegroups.com
OF COUUUUUUUUURSE!!!!!!!

Thx for this illumination!

--
You received this message because you are subscribed to the Google Groups "Eiffel Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to eiffel-users...@googlegroups.com.
Visit this group at https://groups.google.com/group/eiffel-users.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages