I'm not quite sure the uses for the different variables in CoffeeScript
class Cow
#utters = 1
constructor: (#name) ->
mutate:->
alert #utters
heads: 1
feet = 9
c = new Cow
From my investigation, it seems heads is public and feet is private. My confusion comes in when figuring out name and utters. For name it more or less compiles to this.name = name and for utters it compiles to Cow.utters = 1.
So my questions are. What is the scope of utters and how should it be accessed? What is the scope of name and how should it be accessed?
Let us look at these one by one.
For the first one:
class Cow
#utters = 1
this is the class itself when you hit #utters = 1 so this #utters is sort of a class variable. The JavaScript version is this:
var Cow = (function() {
function Cow() {}
Cow.utters = 1;
return Cow;
})();
Subclasses will be able to see this but they'll have their own copy of it; so, for this:
class CowCow extends Cow
m: ->
CowCow.utters = 11
CowCow.utters starts out as 1 but will be 11 after (new CowCow).m() and Cow.utters will stay at 1 all the way through.
The second one:
class Cow
heads: 1
is essentially a default instance variable; the JavaScript version looks like this:
var Cow = (function() {
function Cow() {}
Cow.prototype.heads = 1;
return Cow;
})();
The Cow.prototype.heads = 1; part means that heads is inherited and attached to instances rather than classes.
The result is that this:
class Cow
heads: 1
class CowCow extends Cow
m: ->
alert #heads
#heads = 11
(new CowCow).m()
alert (new Cow).heads
alerts 1 twice.
The third one:
class Cow
feet = 9
m: -> alert feet
is another sort of class variable but this one is very private: feet is not inherited, not visible to subclasses, and not visible to the outside world. The JavaScript version is this:
var Cow = (function() {
var feet = 9;
function Cow() {}
Cow.prototype.m = function() { return alert(feet) };
return Cow;
})();
so you can see that:
feet will be visible to all Cow methods.
All Cow instances will share the same feet.
feet is not public in that you can't get at it without calling a Cow method (class or instance, either will do).
feet is not visible to subclasses since it isn't a property of the class and it isn't in the prototype (and thus it isn't inherited by instances of subclasses).
Summary: #utters is sort of a traditional class variable, heads is a public instance variable with a default value, and feet is sort of a private class variable.
Related
I'm a beginner learning dart from the book dart apprentice and I reached where they were discussing constructors in dart classes, the book was implying that constructors create instances of the class which I understood but I needed more info about constructors. So I googled and some results repeated what was already in the book about it being used to create instances of a class while others also showed that it's used to instantiate class properties, but my problem is with the other answer which I found that they are used to instantiate properties of a class, but my question is: I instantiate all class properties when I create the class by declaring the property variables, like this:
class UserClass{
userClassProperty = "";
anotherUserClassProperty = ""; }
why is the constructor also needed to instantiate class properties?
Often, values are unique to every class instance.
Consider the following example:
class Point {
final int x;
final int y;
const Point(this.x, this.y);
double get distanceToOrigin => sqrt(x * x + y * y);
}
If the x and y values were defined inside the class, it would be pretty useless. Instead, different Point objects can be instantiated with different values, which means the same code can be used for different situations.
Ok, so constructors instantiate or start a class by collecting all the data the class needs to start to start working. Constructors are so important that the dart compiler provides one even if you don't explicitly create one. For example, you create a class for mammals like this :
class Mammal{
String name = "cat";
int numberOfLegs = 2;
}
Although you don't explicitly add a constructor the dart compiler adds a default constructor like this :
class Mammal{
Mammal(); //This is added by dart during the class instantiation by default.
String name = "cat";
int numberOfLegs = 2;
}
Yeah, that's how crucial constructors are to the dart compiler.
And on the topic of why are they necessary even when you declare all the properties by yourself in the class, as hacker1024 said it would make the class pretty useless, as the point of the existence of classes is to create variants but with different properties. Not adding a constructor to your class and defining all the properties in the class would mean that your class doesn't take property arguments which in turn also means that different variants of your class can't be created. Again this goes directly against the point of the existence of dart classes. For example, you have a class like this :
class Mammals{
Strig name = "Human";
int numberOfLegs = 2;
bool hasFur = false;
}
final cat = Mammal();
final human = Mammal();
print(cat.numberOfLegs); //Prints 2
//2
print(human.numberOfLegs); //Also prints 2
//2
print(cat.hasFur);
// false
Yeah, this class is problematic. Cats with 2 legs? You would agree with me that that's not how things are in reality. And also the class is pretty useless in the sense that it's not modular, no matter which kind of mammal we create be it a cat, a sheep or even a cow the name property is going to be the default one we set, that is "Human". When we create a class to simulate mammals we want to be able to define what kind of properties it has, not use some fixed values. So you want to create a class which has a constructor like this :
class Mammals{
Mammals(String name,int noOfLegs, bool hasFur){
this.name = name;
this.noOfLegs = noOfLegs;
this.hasFur = hasFur;
}
String name = "";
int noOfLegs = 0;
bool hasFur = False;
}
final cat = Mammal("Cat", 4, True); //Now you can pass in the properties ou want.
final human = Mammal("Human", 2, false);
print(cat.name); //This prints the customized name of the object cat instead of some fixed value
//Cat
print(human.name); //This prints the customized name of the object human
Now we have two instances of the class with separate property values.
Although this adds a little more code, the modularity benefit is worth it.
I am struggling with the concept of getters and setters in Dart, and the more I read, the more I cannot grasp the underlying purpose. Take for example the following code:
main() {
Car car = new Car();
car.doors = 44;
print(car.doors); // 44
}
class Car {
int doors = 4;
}
Later, I decide to make “doors” a private variable, so I do the following:
main() {
Car car = new Car();
car.doors = 44;
print(car.doors); // 44
}
class Car {
int _doors = 4;
int get doors => _doors;
set doors(int numberOfDoors) => _doors = numberOfDoors;
}
According to the code, _doors is now a private variable, and so I cannot access it in main(). However, by manipulating doors, I can indirectly change the value of _doors, which is what I thought I wanted to prevent in the first place by making it a private variable. So what is the purpose of making a previously public variable into a private one, if you can still indirectly manipulate it? And, how are getters and setters even working to change the properties of these variables? I am trying to understand the fundamental concept, because without that, I don't understand how or why getters and setters are used.
Instance variables in Dart have implicit getters and setters. So for your example code, it will operate in exactly the same way, since all you have done is changed from an implicit getter and setter to an explicit getter and setter.
The value of explicit getters and setters is that you don't need to define both if you don't want. For instance we can change your example to only define a getter:
main() {
Car car = new Car();
print(car.doors); // 4
car.doors = 6; // Won't work since no doors setter is defined
}
class Car {
int _doors = 4;
int get doors => _doors;
}
Additionally, you can also add extra logic in a getter or setter that you don't get in an implicit getter or setter:
class Car {
int _doors = 4;
int get doors => _doors;
set doors(int numberOfDoors) {
if(numberOfDoors >= 2 && numberOfDoors <= 6) {
_doors = numberOfDoors;
}
}
}
The getter and setter functions allow us to make the class appear to have a property, without a explicit property being declared (_doors in your case). The property value may be calculated from other properties.
The getters and setters allow us to execute arbitrary code when the property is get or set.
Omitting a setter makes the property immutable.
An abstract class may declare getters and setters without bodies as part of a required class interface.
This works :
class Foo
class #_Bar
#narf = ''
#point : ->
#narf = 'what'
class #_Baz extends #_Bar
#point : ->
#narf = 'woo'
super()
This does not
class Foo
class #_Bar
#narf = ''
#point = ->
#narf = 'what'
class #_Baz extends #_Bar
#point = ->
#narf = 'woo'
super()
running Foo._Baz.point() will throw and error.
Please someone explain what is going on here.
It seems like a bug in the compiler to me. Writing
class X
#classMethod: ->
and
class X
#classMethod = ->
should be equivalent, yet super compiles differently across the two methods. In the first, it compiles correctly:
X.__super__.constructor.classMethod.apply(this, arguments);
In the second, it compiles as if classMethod were an instance method:
X.__super__.classMethod.apply(this, arguments);
This works:
class Foo
class #_Bar
#narf = ''
point : ->
#narf = 'what'
class #_Baz extends #_Bar
#point = ->
#narf = 'woo'
super()
alert Foo._Baz.point() # 'what'
alert new Foo._Bar().point() # 'what'
That is, the compiled #point= super ends up pointing to the instance point:. Its JS is: _Baz.__super__.point.call(this), which is _Bar.prototype.point.call(this). (extends defines: child.__super__ = parent.prototype).
It's clear from past Coffeescript changes that #point: is the intended syntax for static (class) methods (and used that way in the compiler itself).
There are a couple of fixes now on github. https://github.com/jashkenas/coffee-script/issues/3232
Currently the node tree for a #foo= method is different from that of a #foo: method. Because of that, a node created with = is never passed to the Class addParameters method, and is never flagged as static.
One solution, which will probably be accepted, makes sure both forms produce the same node tree.
The one I contributed https://github.com/jashkenas/coffee-script/issues/3232#issuecomment-28316501
adds a method to nodes.coffee class Class. This method is a stripped down version of addParameters, and specifically checks a = node tree.
If you need a fix in your own Coffee compiler, modify your src/coffee-script/nodes.coffee file, compile it, and put the resulting node.js in the lib directory (or use the cake build).
I've detected a very weird behavior in coffeescript.
class Foo
list: []
add: (val)->
#list.push(val)
x = new Foo()
x.add(1)
console.log(x.list.length) // 1
y = new Foo()
y.add(1)
console.log(y.list.length) // 2
So as you see the #list property got shared between the two class instances in a strange way.
I've never faced similar issue before, in coffeescript.
Convert it to JavaScript:
var Foo, x, y;
Foo = (function() {
function Foo() {}
Foo.prototype.list = [];
Foo.prototype.add = function(val) {
return this.list.push(val);
};
return Foo;
})();
As you can see, Foo.prototype.list is a property of the prototype, not of an instance of your class. There's only one array and it will be shared across all of the instances of your class.
To make list an instance variable, add it to the constructor:
class Foo
constructor: ->
#list = []
add: (val)->
#list.push(val)
Say I'm declaring a class Game.
class #Game
constructor: ->
#id = Game.generateNewGameId() # <---
player1: null
player2: null
#generateNewGameId: -> "blahblah23"
Here, I'm using generateNewGameId as Game.generateNewGameId().
Is this the right way or is there a better way? I've tried using this::generateNewGameId() but the scope's different.
If you really want generateNewGameId to be a class method then you can use #constructor to get at it:
Returns a reference to the Object function that created the instance's prototype. Note that the value of this property is a reference to the function itself [...]
So something like this:
class Game
constructor: ->
#id = #constructor.generateNewGameId()
#generateNewGameId: ->
"blahblah23"
Note that this will do The Right Thing if you subclass Game:
class C extends Game # With an override of the class method
#generateNewGameId: ->
'pancakes'
class C2 extends Game # or without
Demo (open your console please): http://jsfiddle.net/ambiguous/Vz2SE/
I think the way you are accessing it is OK. You can also do #constructor.generateNewGameId() if you don't want to write Game.generateNewGameId() for some reason, but i'd prefer the later. Update: as #mu is too short mentions, the #constructor allows you to get the constructor of the instance, which can be differ from Game (in a subclass) so it has greater flexibility; if that flexibility is required in this case, definitely go for that :)
If the generateNewGameId function will not be accessed from outside the Game class, you can use a private function instead of a class method:
class #Game
gameIdCounter = 0
generateNewGameId = -> gameIdCounter++
constructor: ->
#id = generateNewGameId()
player1: null
player2: null
console.log (new Game).id # -> 0
console.log (new Game).id # -> 1
Example at coffeescript.org.
There both gameIdCounter and generateNewGameId are private variables inside the Game class.