0

I realized I don't know how to do something I think is pretty important, which is to create a 'subclass', or in other words a nested object upon an instance which has functions which refer to the instance.

For example, I would like to be able to do this:

sequence = new Sequencer(2, [true, true])
sequence.is_valid # returns true or false

using the following code:

class Sequencer

  Validations:

    correct_sequence_length: ->
      @division == @sequence.length

    positive_length: ->
      @division > 0

  constructor: (args) ->
    { @sequence, @division } = args

  is_valid: ->
    @Validations.correct_sequence_length() &&\
    @Validations.positive_length()

However it seems that since Validations is an object, it has its own scope and the this in its methods doesn't refer to the instance, but rather the Validations object. This means it can't access @sequence or @tempo. I also tried using an arrow function but it didn't work.

Is the best way to deal with this to make Validations its own class?

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • Coffeescript or ES6? Please decide, they're quite different. – Bergi May 09 '17 at 21:26
  • [Yes, you need an extra class](http://stackoverflow.com/q/15884096/1048572) if you want to nest properties. – Bergi May 09 '17 at 21:28
  • @Bergi I prefer coffeescript, but v2 outputs ES6 classes so it's not necessarily unrelated. If you have a solution that works in ES6 but not coffeescript I'd be curious to see it anyway. – max pleaner May 09 '17 at 21:31

1 Answers1

0

Yes, you'll need an extra class that contains a reference to the Sequencer:

class Sequencer

  @Validations: class
    constructor: (@target) ->

    correct_sequence_length: ->
      @target.division == @target.sequence.length

    positive_length: ->
      @target.division > 0

  constructor: ({ @sequence, @division }) ->
    @validations = new Sequencer.Validations(@)

  is_valid: ->
    @validations.correct_sequence_length() &&
    @validations.positive_length()

(for convenience I nested it as a static property of Sequencer, but there's no need for that).


Arrow functions would work if you didn't make validations an object:

class Sequencer

  constructor: ({ @sequence, @division }) ->

  validations: ->
#             ^^^^
    correct_sequence_length: =>
      @division == @sequence.length

    positive_length: =>
      @division > 0

  is_valid: ->
    v = @validations()
    v.correct_sequence_length() && v.positive_length()

You can create that object with the arrow functions in the constructor as well:

class Sequencer

  constructor: ({ @sequence, @division }) ->
    @validations =
      correct_sequence_length: =>
        @division == @sequence.length
      positive_length: =>
        @division > 0

  is_valid: ->
    @validations.correct_sequence_length() &&
    @validations.positive_length()
Bergi
  • 630,263
  • 148
  • 957
  • 1,375