Qu'est-ce qui ne va pas dans cette classe dans CoffeeScript ??
@module "Euclidean2D", -> class @Point constructor: (x,y) -> return if Float32Array? then Float32Array([ x, y ]) else Array(x,y)
Je veux qu'il se comporte comme:
p = new Point(1.0,2.0); p[0] == 1.0 p[1] == 2.0
Mais le test avec Jasmine reçoit "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
Y a-t-il une erreur dans CoffeeScript ou dans Jasmine?
Tout cela se trouve dans un module comme:
@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
Dans la console Chrome, je reçois:
a = new Euclidean2D.Point(1.0,2.0) -> Point a[0] undefined b = new Float32Array([1.0,2.0]) -> Float32Array b[0] 1
EDIT: encore une fois désolé
A résolu en utilisant une combinaison de réponses @brandizzi et @ arnaud576875. Le @module prononcé dans le Wikipédia CoffeeScript officiel n'a pas fonctionné. Le résultat est:
class @Point constructor: (x, y) -> return if Float32Array? then Float32Array([ x, y ]) else Array(x,y)
Vous devez utiliser le new
pour créer une instanciation de l'objet:
p = new Euclidean2D.Point(1.0,2.0)
Si vous souhaitez renvoyer une matrice du constructeur, faites-le explicitement:
constructor: (x,y) -> return if Float32Array? then Float32Array([x,y]) else Array(x,y)
(Par défaut, Coffeescript ne renvoie pas les valeurs du constructeur, donc vous devez le faire explicitement.)
Vous auriez pu le faire aussi:
class @Point constructor: (x,y) -> @[0] = x @[1] = y
Vous définissez un constructeur, mais vous attendez à ce qu'il se comporte comme une fonction. Le constructeur, cependant, ne définit que des valeurs dans l'objet à renvoyer. Étant donné que votre constructeur ne définit aucun attributs dans l'objet d'initialisation, il n'est vraiment pas utile.
Vous avez quelques alternatives:
Initialiser la classe comme @amaud suggéré.
Renvoie la valeur du constructeur à mesure que @amaud a suggéré (ce qui n'a pas beaucoup de sens pour moi. Ce n'est pas la fonction d'un constructeur que je le sens. Dans ce cas, la solution # 3 semble mieux).
Définissez une fonction au lieu d'une classe. IMHO, est la solution la plus simple et la plus fonctionnelle
@Point = (x, y) -> if Float32Array? then Float32Array([x,y]) else Array(x,y)
Si vous souhaitez que Point
soit une spécialisation de Float32Array
ou Array
, utilisez l'option n ° 1, mais faites Point
pour hériter de la classe souhaitée:
superclass = if Float32Array? then Float32Array else Array class @Point extends superclass constructor: (x,y) -> @[0] = x @[1] = y
EDIT : @ amaud676875 a posté une question intéressante en tant que commentaire. Comme une réponse raisonnable impliquerait un certain code, je publie la réponse comme une édition.
@amaud, pour vérifier votre point, j'ai écrit le module CoffeeScript suivant:
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
Ensuite, j'ai importé le module dans la console:
coffee> point = require './point' { Point: { [Function: Point] __super__: [ constructor: [Object], first: [Function] ] }, Float32Array: { [Function: Float32Array] __super__: [] } }
Et a créé un Point
:
coffee> p = new point.Point 3, 2 [ 3, 2 ]
Ce Point
a la first()
méthode first()
de Float32Array
:
coffee> p.first() 3
Et instanceof
dit que c'est une instance de Float32Array
aussi:
coffee> p instanceof point.Float32Array true
Donc, je parie de new Point x, y
renvoie une instance de Float32Array
. Bien sûr, c'est une instance de Point
aussi, et ce n'est pas un problème parce que Point
is-a Float32Array
, pour utiliser une expression OOP classique.