R6 icon indicating copy to clipboard operation
R6 copied to clipboard

Diamond inheritance pattern and interfaces

Open romainfrancois opened this issue 5 years ago • 9 comments

Follow up to #9 with perhaps a different spin, and additional context here https://github.com/apache/arrow/pull/2714#discussion_r224381298

When doing R6 promotion of class hierarchies like these: https://arrow.apache.org/docs/cpp/classarrow_1_1io_1_1_random_access_file.html

image

a concept of interfaces à la Java would be useful, perhaps something like the pseudo code:

Seekable <- R6Interface("Seekable", 
  public = list( 
     Seek = function(position){} 
  )
)

RandomAccessFile <- R6Class("RandomAccessFile", 
  inherit = InputStream, 
  implements = list(Seekable), 
  ...
)

romainfrancois avatar Oct 12 '18 07:10 romainfrancois

R being a dynamic language, we could also make this more of a convention instead of introducing another "keyword". E.g. just simply:

RandomAccessFile <- R6Class("RandomAccessFile", 
  inherit = list(InputStream, Seekable),
  ...
)

and we would require that for each inherited method at most one is implemented, and the others are NULL, or a special NULL function.

It might be worth checking how other dynamic languages are doing this.

gaborcsardi avatar Oct 12 '18 07:10 gaborcsardi

The Python way seems too difficult for me, and it is also apparently different in Python 2 and 3.

gaborcsardi avatar Oct 12 '18 08:10 gaborcsardi

IIRC the issue with having them all in inherit was with super$

but yeah I guess the convention could be that super$ means the first and then the other are accessed with something different, e.g. self$interfaces$Seekable$Seek() or something.

romainfrancois avatar Oct 12 '18 08:10 romainfrancois

That's why we would allow only one implementation. This is the one that will be called via super. The other instances of the same method (from other parent classes) must be NULL.

But maybe the implements keyword is better, it is surely more explicit.

gaborcsardi avatar Oct 12 '18 08:10 gaborcsardi

But then with implements we need to take care about inheriting interfaces, etc.

gaborcsardi avatar Oct 12 '18 08:10 gaborcsardi

But then if we have new syntax, we might as well do the original suggestion in #9. Maybe.

gaborcsardi avatar Oct 12 '18 08:10 gaborcsardi

+1 for the suggestion to have interfaces in R6. it is the feature i am missing the most currently, to ensure good design in my class systems

berndbischl avatar Nov 21 '18 19:11 berndbischl

i actually nearly started writing something simple here myself

berndbischl avatar Nov 21 '18 19:11 berndbischl

I'd like to echo support for implementing (no pun intended) some sort of interface mechanism. I think the Java (and probably others) thought through he issues of multiple-inheritance when they landed on 'single inheritance, multiple interfaces'....

So, the idea of introducing the notion of an 'interface declaration' (separate from R6Class, it would be something like R6Interface), and allow the R6Class() to specify an 'implements' list that specifies a set of R6Interface types that will be checked for implementation after the class is defined. Then super$ always knows it's referencing the single inherited type, while the implements specification can specify multiple interfaces that will result in a validation check on the class definition that has the proper methods defined (which also will find implemented methods in the inheritance hierarchy).

This would be really wonderful to introduce, and would really be worth any additional size to the library to support it. This isn't sugar syntax, this is a real gap in functionality.

chrisknoll avatar May 03 '22 04:05 chrisknoll