Skip to content
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

Support for mimicking interfaces/abstract classes #82

Closed
jankowtf opened this issue Feb 16, 2016 · 2 comments
Closed

Support for mimicking interfaces/abstract classes #82

jankowtf opened this issue Feb 16, 2016 · 2 comments

Comments

@jankowtf
Copy link

jankowtf commented Feb 16, 2016

It'd be great to support at least mimicking (after all we're mostly only prototyping OO-related stuff in R) the use of interfaces/abstract classes.

My intention is not trying to make R6 and/or "OOP in R" a full-fledged equivalent of features in other "true" OO-languages. I simply think we could add a little useful feature here and there :-)

Motivation

My actual motivation and/or use case for this is as follows:

As 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 (dependency inversion principle) of the SOLID principles of OOD (detailed explanation by "Uncle Bob")

Even though R6 does not explicitly support interfaces, I can nevertheless perfectly mimick them with R6 and this helps me a lot with communicating my software designs to our OO-programmers.

However, I need to give up my value for inherit in R6Class for that which becomes a bit of a problem when I actually want to inherit from other concrete (as opposed to the abstract interface class).

Example

One probably could go at it from the perspective of multpile inheritance, but that seems rather complicated to implement.

Another option is to mimick the use of abstract classes or interfaces. I did try to sketch a (hopefully) pragmatic solution for that in this pull request. This is also related to my comments in #9.

devtools::install_github("rappster/R6", ref = "feat_interface")
library(R6)

Correct implementation of interface and "standard inheritance":

  IFoo <- R6Class("IFoo",
    public = list(foo = function() stop("I'm the inferace method"))
  )
  BaseClass <- R6Class("BaseClass",
    public = list(foo = function(n = 1) private$x[1:n])
  )
  Foo <- R6Class("Foo", implement = IFoo, inherit = BaseClass,
    private = list(x = letters)
  )

> Foo$new()
<Foo>
  Implements interface: <IFoo>
  Inherits from: <BaseClass>
  Public:
    clone: function (deep = FALSE) 
    foo: function (n = 1) 
  Private:
    x: a b c d e f g h i j k l m n o p q r s t u v w x y z

Interface not implemented correctly (method not implemented):

 Bar <- R6Class("Bar", implement = IFoo,
    private = list(x = letters)
  )
> Bar$new()
Error in Bar$new() : 

Non-implemented interface method: foo

Proof of concept for dependency injection

This is a draft that elaborates a bit on the motivation and possible implementation approaches for interfaces and inversion of dependency in R6

@hadley
Copy link
Member

hadley commented Jul 17, 2017

I think this is a reasonable idea, but it's out of scope for R6 which is deliberately very minimal.

@chrisknoll
Copy link

Please reconsider this: it's an opt-in feature (you don't need to say you implement a feature, and existing code doesn't need to know the existence of it).

The implementation seems to be light weight: new field for implements on an R6 definition, and you check that the functions from the interface definition exist when you $new it. Ez-Pz.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants