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

Complementary use of implements #297

Open
jorgebg opened this issue Apr 12, 2013 · 7 comments
Open

Complementary use of implements #297

jorgebg opened this issue Apr 12, 2013 · 7 comments

Comments

@jorgebg
Copy link

jorgebg commented Apr 12, 2013

I am proposing a complementary use of the implements keyword, out of the class definition.
It would check if the properties of the given class matches with the interface properties.
Here is an example:

class ITest
  foo: (x)->
  @bar = (x,y)->

class Test1
  foo: (x)->
  @bar = (x,y)->

class Test2
  foo: ->

Test1 implements ITest  # true
Test2 implements ITest  # false
Test2 implements! ITest # Error "class property Test2.bar is not implemented." + "object property Test2.foo number of params should be >= 1."

The last three lines should compile to something like:

implements$(Test1, ITest, false)
implements$(Test2, ITest, false)
implements$(Test2, ITest, true)

This function checks if the properties of the given class matches with the interface properties.

/*
  cls: Object or class to check
  itf: Interface class
  ensure: If true, errors throws an exception
*/
implements$ = (cls, itf, ensure=false) ->
  # If it is an object, get its class
  cls = cls.constructor if typeof cls is \object

  # We are going to check class properties and object properties
  checks =
    class: [cls, itf] # Class and interface class
    object: [cls.prototype, itf.prototype] # Object and interface object

  errors = []
  # For class and object
  for type, [target, source] of checks # Note that `source` is the interface
    # For each property
    for key, value of source
      target-value = target[key]
      source-value = source[key]
      error = switch
      # implemented?
      | not target-value => "is not implemented"
      # it should be a function...
      | typeof source-value is \function => switch
        # but it is not
        | typeof target-value isnt \function =>
          "must be a function"
        # but the number o params doesn't match
        | source-value.length > target-value.length =>
          "arguments number must be >= #{source-value.length}"
      if error
        errors.push "The #{type} property #{cls.displayName}.#{key} #{error}."

  implemented = errors.length is 0
  if not implemented and ensure
    throw new Error errors.join "\n"
  implemented

What do you think?

In first place, I tried to name this function as implements and use it with an infix function call:

Test `implements` ITest

But currently the compiler throws an Unexpected identifier error when I define the function with that name. Then I realized that it would be an interesting feature for LiveScript 😋.

At least, would it be possible to allow the use of implements outside the class definition?

@jorgebg
Copy link
Author

jorgebg commented Apr 13, 2013

Another improvement 😄 allowing classes to implement other classes:

ITest1 =
  foo: (x)->

class ITest2
  foo: (x)->
  @bar = (x,y)->

class Test1 implements ITest1

class Test2 implements ITest2

It would call the following function instead of calling importAll$ directly:

implement$ = (cls, itf) ->
    cls import all itf
    if typeof itf is \function
      cls.prototype import all itf.prototype

@vendethiel
Copy link
Contributor

currently we have

class A
  foo: 'bar'

class B
  import A::
console.log B.foo #=> 'bar'

class C implements A::

console.log C::foo #=> 'bar'

@jorgebg
Copy link
Author

jorgebg commented Apr 13, 2013

Yes but the static properties are not inherited, am I wrong?

@jorgebg
Copy link
Author

jorgebg commented Apr 28, 2013

Bump! What about allowing declare functions with the name implements outside class definitions?

@gkz
Copy link
Owner

gkz commented Apr 28, 2013

The implements$ function is an not insignificant addition in terms of complexity (compared to our other utility functions).

@jorgebg
Copy link
Author

jorgebg commented Apr 28, 2013

Ok, I agree 😃 I am only asking for allowing the use of implements outside class definitions in order to be able to declare functions and variables with the id implements

@gkz
Copy link
Owner

gkz commented Apr 28, 2013

Oh I see. Yes potentially.

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