How to set object properties with classes in CoffeeScript

I'm trying to write a program that takes a number and validates it according to the Luhn formula.

How do I set object properties in the class in CoffeeScript? I want to do this:

class Luhn
  constructor: (@number)  ->

  lastDigit: @number % 10

But this produces:

function Luhn(number) {
  this.number = number;
}

Luhn.prototype.checkDigit = Luhn.number % 10;

Which returns undefined, because it's trying to access a class variable.

When setting the prototype, you can do this, though:

function Luhn(number) {
  this.number = number;
}

Luhn.prototype.lastDigit = function() {
  return this.number % 10
}

Now an instance of the Luhn class has a function lastDigit() which works.

Is there a way of setting object properties in the class in CoffeeScript? I know I can set it in the constructor, like this:

class Luhn
  constructor: (@number)  ->
    @lastDigit: @number % 10

But I want to set other, more complicated properties, and I don't want my constructor to become a mess. This is an idea, but it still kinda sucks:

class Luhn
  constructor: (@number)  ->
    @lastDigit: @number % 10
    @complicatedProperty1 = getComplicatedProperty1(@number)
    @complicatedProperty2 = getComplicatedProperty2(@number)

What's the best way to go about this?

Upvotes: 0

Views: 1009

Answers (1)

mu is too short
mu is too short

Reputation: 434985

Set them in the constructor, that's the only place where you have an instance to work with.

Alternatively, use a method instead of a simple property:

class Luhn
  constructor: (@number)  ->

  lastDigit: -> @number % 10

or:

class Luhn
  constructor: (@number)  ->

  lastDigit: -> @number % 10

  complicatedProperty1: ->
    @_complicatedProperty1 ?= getComplicatedProperty1(@number)

The caching inside complicatedProperty1 assumes that @number won't be changing and that getComplicatedProperty1(@number) won't return null or undefined.

A CoffeeScript class isn't really a C-style struct so exposing everything as plain properties isn't the best idea ever. If you need easy access to just the properties, then provide a toJSON or serialize method to do so without exposing your internals to accidental modification:

toJSON: ->
  number: @number
  lastDigit: @lastDigit()
  complicatedProperty1: @complicatedProperty1()

I used toJSON as the name as JSON.stringify will call that method when it tries to stringify an object:

If an object being stringified has a property named toJSON whose value is a function, then the toJSON method customizes JSON stringification behavior: instead of the object being serialized, the value returned by the toJSON method when called will be serialized.

so toJSON is a natural name of serialization functions in (Coffee|Java)Script.

Upvotes: 1

Related Questions