-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple inheritance #9
Comments
I'm wary of multiple inheritance - I think I'd need to know the problem space better before I'd really consider adding it. Coincidentally, I saw this recently: |
I agree it is a difficult problem. That's probably the reason why many languages screwed it up, and now people are wary. :) Anyway, imho that link and the original SE question list a lot of problems that do not come up it you do things "right". Some of the problems simply don't come up, because R has dynamic typing. Others can be handled easily. E.g. somebody says that the order in which the superclasses are listed matters. Well, no, it does not matter if you do it properly. (Yes, it might for C++, Java or whatever your language is.) Also, nobody seems to be aware of the nice MI implementation in Eiffel. This said, I think
So I think I'll close this now, sorry for the noise. |
The need for multiple inheritance has arisen for a package I'm developing that using R6 classes for the Google Analytics Management and Google Tag Manager APIs. I'm working around the limitation of R6 not currently supporting multiple inheritance, by copying shared fields and methods. This is achieved by accessing class definitions via the elements of the class generators, e.g. Here are links to the source code to see what this is looking like:
I've found it much easier to get where I've wanted to with R6, but now that I have a working solution I'm considering translating this to S4 so that I can attempt to redefine the solution in a way that supports multiple inheritance - this will be a challenge though. Any suggestions would be appreciated. |
@jdeboer: I've ran into a similar requirement (multiple inheritance). I tried to follow your hack, but it seems that the underlying scripts have changed at least for your pointer to Ressource and collection super classes. Would you mind updating these reference? I'm really eager to find out how you made it happen. @wch: +1 for @gaborcsardi's request. ContextAs my R prototypes for web-app-like stuff need to be as close as possible to design patterns and dependency injection containers used in our production language (C#), I've come to like to use interface (or abstract) classes to decouple my code and comply with the D of the SOLID principles of OOD: Even though R6 does not explicitly support interfaces, I can nevertheless perfectly mimick them with R6 (see example below). This helps me a lot with communicate my software designs to our OO-programmers. ExampleBefore inversion of dependency:
After inversion of dependency:
A bit mor on why this makes sense with regard to OOD: Using inheritance from base classes to simplify design: So far, so good. However, I'd also like to simplify my design by definining certain concrete base classes that some of my other concrete classes can inherit from.
Combining "interface implementation" and base clases inheritance: This is where I would need multiple inheritance so something like this would work (PSEUDO CODE):
Currently, my value for Alternatively, it would be great to explicitly support a differentiation between interface and concrete classes somehow. For example:
|
I gave it a second thought and realized that's it's not really multiple inheritance per se that I want/need, but rather some sort of better mimicking the use of interfaces/abstract classes without giving up So I went ahead and had a go at tweaking R6 a bit so it would allow me to distinguish between Probably tons of reasons why this is a bad idea ;-) But for now, it gets the job done. |
Hi @rappster Here are the source file in I've actually started working on a new approach, which is currently on hold and not yet functioning at the moment, where I intend on using R6 and S4 in combination: https://github.com/jdeboer/ganalytics/blob/dev/R/WIP/management-api-classes-V3.R Wish I had more time to work on this at the moment, but I've enrolled myself in full time study while also working, so a bit stretched. My apologies for taking a while to get back to you. |
Maybe my use case is no multiple inheritance at all, maybe it is to short sighted ... but let's see. Some background info: Playing around with R6 I developed a class binding together text and data (rtext). On my way I split up parts of the class because they are separate blocks of functionality and reading code and maintainig code should be better this way. So what I end up is somthing like a class dependecy like that
Which I have to write like this ... R6_extension <- R6::R6Class( classname = "R6_extension", ... )
rtext_base <- R6::R6Class( classname = "rtext_base", inherit = R6_extension, ... )
rtext_extension_1 <- R6::R6Class( classname = "rtext_extension_1", inherit = rtext_base, ... )
rtext_extension_2 <- R6::R6Class( classname = "rtext_extension_2", inherit = rtext_extension_1, ... )
rtext_extension_3 <- R6::R6Class( classname = "rtext_extension_3", inherit = rtext_extension_2, ... )
rtext <- R6::R6Class( classname = "rtext", inherit = rtext_extension_3, ... ) ... which is (possible but) tedious whenever I extend the functionality by another 'module' (sub-class). Now would it not be nice to have something like that: rtext <-
R6::R6Class(
classname = "rtext",
inherit =
list(
R6_extension,
rtext_base,
rtext_extension_1,
rtext_extension_2,
rtext_extension_3
),
...
) ... which works like just a series of inherits? |
Why is this issue closed since 3 years ? It seems like multiple inheritences are still not availiable in R6. Will you reconsider implementing the possibility of multiple inheritance ? If so, why ? |
So how do you propose the diamond problem is handled? |
Well there is a lot of ways to handle a diamond issue in a multiple inheritance framework. My english is a little bad so i'm not gonna sketch them, i refer you to some exemples there : https://en.wikipedia.org/wiki/Multiple_inheritance#Mitigation My thoughts : there are 2 easy way and a harder one of handling the issue : I'll sketch a little more the second solution :
I'm not enough aware of the implementation choices in R6 to be able to choose the best option, since there are a lot of them -- sorry -- , but there is definitely a solution to the problem. Glad to explain more if needed :) |
Yep that makes sense. |
Well taking super as a list could make a lot of sence if we choose the ordered parrent way of dispatching methods. But the goal is to keep things as they are and not to break everyone's code by changing the definition of super. Keep in mind that the system will have to stay the same if no multiple inheritance are defined. keep also in mind that if no diamond problems are found, everything should behave the same. |
Wouldn't have to be necessarily ordered, a named list would be handy, where the names are the classes respectively, something like this perhaps for example:
|
You'l loose the
syntax, and have to replace it by
? I'll prefere tweaking the super object such that :
still works. |
Yeah you would probably lose first syntax. I am still trying to decide whether that is a good or a bad thing. |
Just an idea for a cool feature. Probably not needed much, but sometimes handy, especially if it is possible to implement it in a simple and useful way. And not too many languages have done this properly, so R6 would be a standout. :)
A possible use-case is a class that implements a feature that can be useful in many other classes as well. E.g. you could have a
pretty_printer
class that has some fancyprint
method. This is potentially useful for any class. So in a project, your classfoo
just inherits frompretty_printer
, in addition to its normal inheritance hierarchy, and thenfoo
has a niceprint
method. There can be many similar features if course.There could be of course several other examples. E.g. think about a class hierarchy of visualization types. You can have
dynamic_plot
s, and alsoline_plot
s, but of course it should be possible to inherit from both of these to create adynamic_line_plot
. An alternative would be to have adynamic_plot
and aline_plot
as members, but that is less expressive.I personally like the implementation of multiple inheritance in the Eiffel language:
undefine
the one(s) you don't want.rename
an inherited member. This is useful if you inherit methods with identical names from two (or more) superclasses, and want to use both of them. This seems challenging to implement in R6.The text was updated successfully, but these errors were encountered: