What is wrong in this class in CoffeeScript ??
@module "Euclidean2D", ->
class @Point
constructor: (x,y) ->
return if Float32Array? then Float32Array([ x, y ]) else Array(x,y)
I want it to behave like:
p = new Point(1.0,2.0);
p[0] == 1.0
p[1] == 2.0
But testing with Jasmine I get "Expected undefined to equal 1."
describe "Point", ->
beforeEach ->
@point = new Euclidean2D.Point(1.0,2.0)
it "extracts values", ->
(expect @point[0]).toEqual 1.0
(expect @point[1]).toEqual 2.0
Is there an error in CoffeeScript or in Jasmine ??
Also all of it is in a module like:
@module = (names, fn) ->
names = names.split '.' if typeof names is 'string'
space = @[names.shift()] ||= {}
space.module ||= @module
if names.length
space.module names, fn
else
fn.call space
In the Chrome Console I get:
a = new Euclidean2D.Point(1.0,2.0)
-> Point
a[0]
undefined
b = new Float32Array([1.0,2.0])
-> Float32Array
b[0]
1
EDIT: , again.. sorry
Has solved using an combination of @brandizzi and @arnaud576875 answers. The @module prposed in the official CoffeeScript Wiki did not work. The result is:
class @Point
constructor: (x, y) ->
return if Float32Array? then Float32Array([ x, y ]) else Array(x,y)
You should use new
to instantiate the object:
p = new Euclidean2D.Point(1.0,2.0)
If you want to return an Array from the constructor, do it explicitly:
constructor: (x,y) ->
return if Float32Array? then Float32Array([x,y]) else Array(x,y)
(By default, Coffeescript doesn't return values from the constructor, so you have to do it explicitly.)
You could have done that, too:
class @Point
constructor: (x,y) ->
@[0] = x
@[1] = y
You are defining a constructor but expecting that it behaves like a function. The constructor, however, just sets values in the object to be returned. Since your constructor does not set any attributes in the initializing object, it really does not useful.
You have some alternatives:
Initialize the class as @amaud sugested.
Returns the value from the constructor as @amaud sugested (which does not make much sense to me. This is not the function of a constructor as I feel it. In this case the solution #3 seems better).
define a function instead of a class. IMHO, is the most simple and functional solution
@Point = (x, y) -> if Float32Array? then Float32Array([x,y]) else Array(x,y)
If you want Point
to be either a specialization of Float32Array
or Array
, use the option #1 but make Point
to inherit from the class you want:
superclass = if Float32Array? then Float32Array else Array class @Point extends superclass constructor: (x,y) -> @[0] = x @[1] = y
EDIT : @amaud676875 posted an interesting question as a comment. Since a reasonable answer would involve some code, I am posting the answer as a edit.
@amaud, for verifying your point, I wrote the following CoffeeScript module:
class Float32Array extends Array
first: -> # Just for testing
@[0]
superclass = if Float32Array? then Float32Array else Array
class @Point extends superclass
constructor: (x,y) ->
@[0] = x
@[1] = y
Then I imported the module in the console:
coffee> point = require './point'
{ Point: { [Function: Point] __super__: [ constructor: [Object], first: [Function] ] },
Float32Array: { [Function: Float32Array] __super__: [] } }
and created a Point
:
coffee> p = new point.Point 3, 2
[ 3, 2 ]
This Point
has the first()
method from Float32Array
:
coffee> p.first()
3
and instanceof
says it is an instance of Float32Array
, too:
coffee> p instanceof point.Float32Array
true
So I bet new Point x, y
returns an instance of Float32Array
. Of course it is an instance of Point
, too, and it is not a problem because Point
is-a Float32Array
, to use a classical OOP expression.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.