Adam Grant
Adam Grant

Reputation: 13105

Specify "super" of nth parameter in Coffeescript class's function

Regarding this Message class,

class Message
  constructor: (@type) ->

  log: (@title, @text, @delay, @class) ->
    $.growl
      title: @title
      text: '<br>' + @text
      type: @type
      delay: (@delay || 1500)
      class: @class

class Success extends Message
class Error extends Message
class Info extends Message
  log: ->
    super 10000
class Warning extends Message

s = new Success 'success'
e = new Error 'danger'
i = new Info 'info'
w = new Warning 'warning'

With four different kinds of Messages, I want to make the extended Info always pass in a @delay of 10000. If this were the first param of log, I could just say

log: ->
  super 10000

But in this case, it's the third param, how do I override just that so that if I say

i.log('hello')

It will create a growl that says "hello" but with a delay of 10 seconds?

Of course, I could just move @delay to be the first parameter, but I plan to make more overrides similar to this one for other parameters. Is there a way to do this?

Upvotes: 0

Views: 77

Answers (3)

Robert Rossmann
Robert Rossmann

Reputation: 12129

Without any fancy argument list manipulation, this is probably the best you can do while keeping it simple and understandable:

class Info extends Message
  log: (@title, @text, @delay, @class) ->
    super @title, @text, 1000, @class

Upvotes: 0

hpaulj
hpaulj

Reputation: 231385

I think this does what you want, though I've made some guesses. I've also modified it so it runs in the Coffeescript 'try it' browser window. And removed some extra stuff.

growl = (arg)->  # sub for $.growl
  alert ["#{k}:#{v}" for k,v of arg].join(', ')
class Message
  constructor: (@type='msg') ->
  def_delay: 1500
  log: (title, text, delay=0) ->
    growl
      title: title
      text: '<br>' + text
      type: @type
      delay: (delay ||@def_delay)

class Success extends Message
  constructor: (@type='success') ->
class Info extends Message
  constructor: (@type='info') ->
  def_delay : 10000

new Success().log('title','txt')
new Info().log('title','txt')

I don't know why you used @title etc in the log args, unless you wanted to save those values for later use. That @arg form is handy in the constructor arguments, but not commonly used in other functions.

I handle your default delay with an instance variable, def_delay. That could also have been set via the constructor as @delay. I think you were barking up the wrong tree with the super 10000. I assume your info log still needs arguments like title.

I also gave @type a default value, that varies with class.

Upvotes: 1

mu is too short
mu is too short

Reputation: 434685

Declare your log override as a variadic function to get easier access to the argument list as an array and then simply change the argument array's second last value as needed and splat it back to super:

class Info extends Message
  log: (args...) ->
    args[args.length - 2] = 10000
    super args...

Demo: http://jsfiddle.net/ambiguous/eHR4n/

Upvotes: 1

Related Questions