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.
Related
The newtypes tutorial shows you how to inherit from a base python class. Can you inherit from your own python class? Something like this?
PyObject *mod = PyImport_AddModule("foomod");
PyObject *o = PyObject_GetAttrString(mod, "BaseClass");
PyTypeObject *t = o->ob_type;
FooType.tp_base = t;
if (PyType_Ready(&FooType ) < 0) return NULL;
though you need to define your struct with the base class as the first member per the documentation so it sounds like this is not possible? ie how would I setup the Foo struct?
typedef struct {
PyListObject list;
int state;
} SubListObject;
What I'm really trying to do is subclass _UnixSelectorEventLoop and it seems like my only solution is to define a python class that derives from my C class and from _UnixSelectorEventLoop with my C class listed first so that it can override methods in the other base class.
I think you're basically right on your assessment:
it seems like my only solution is to define a python class that derives from my C class and from _UnixSelectorEventLoop with my C class listed first so that it can override methods in the other base class.
You can't define a class that inherits from a Python class because it'd need to start with a C struct of basically arbitrary size.
There's a couple of other options that you might like to consider:
You could create a class the manual way by calling PyType_Type. See this useful answer on a question about multiple inheritance which is another sort of inheritance that the C API struggles with. This probably limits you too much, since you can't have C attributes, but you can have C functions.
You could do "inheritance by composition" - i.e. have you _UnixSelectorEventLoop as part of the object, then forward __getattr__ and __setattr__ to it in the event of unknown attributes. It's probably easier to see what I mean with Python code (which is simply but tediously transformed into C API code)
class YourClass:
def __init__(self,...):
self.state = 0
self._usel = _UnixSelectorEventLoop()
def __getattr__(self, name):
return getattr(self._usel, 'name')
def __setattr__(self, name, value):
if name in self.__dict__:
object.__setattr__(self, name, value)
else:
setattr(self._usel, name, value)
# maybe __hasattr__ and __delattr__ too?
I'm hoping to avoid having to write this C API code myself, but the slots are tp_getattro and tp_setattro. Note that __getattr__ will need to be more comprehensive in the C version, since it acts closer to the __getattribute__ in Python. The flipside is that isinstance and issubclass will fail, which may or may not be an issue for you.
I have already asked a question here where I basically require an instance of a base class to be converted into a subclass (or a new instance of the subclass to be created using the instance of the base class' properties). The conclusion seems to be that the best way to do this is to manually assign every property I need to transfer in the constructor of the base class.
While this is feasible in some cases, it certainly is not when there are many properties to transfer, or when the base class is subject to change — every time you add a property to the base class, the constructor needs to be changed too, so this solutions is inelegant.
I have searched online, and can't see any reason for why this kind of type-casting isn't implemented. The arguments I have seen so far describe this operation to 'not make any sense' (making a minivan from a car was an analogy I saw), question what to do about the non-inherited variables in the subclass, or claim that there must be some better solution for what was trying to be achieved.
As far as I can see, the operation doesn't need to 'make sense' as long as it's useful, so that isn't much of a good reason. What's wrong with adding a few more properties (and perhaps methods/overriding them) to change an instance into a subclass? In the case of the non-inherited variables, that can simply be solved by allowing this kind of type-cast only a constructor is added to the subclass or by just simply setting them to their default values. After all, constructors usually call MyBase.New(...) anyway. What's the difference between using the constructor of the base (essentially creating a new instance of the base) and using an instance which is already initialised? Lastly, I don't think the third argument is well-justified — there are times when all of the other solutions are inelegant.
So finally, is there any other reason for why this kind of casting isn't allowed, and is there an elegant way to circumvent this?
Edit:
Since I don't know a lot about this topic, I think I meant to say 'convert' rather than 'cast'. I'll also add an example to show what I'm trying to succeed. The conversion would only be allowed at the initialisation of the Subclass:
Class BaseClass
Dim x as Integer
Dim y as Integer
End Class
Class Subclass1 : Inherits BaseClass
Dim z as Integer
Sub New(Byval value As Integer)
'Standard initialisation method
MyBase.New()
z = value
End Sub
Sub New(Byval value As Integer, Byval baseInstance As BaseClass)
'Type conversion from base class to subclass
baseInstance.passAllproperties()
'This assigns all properties of baseInstance belonging to BaseClass to Me.
'Properties not in BaseClass (eg. if baseInstance is Subclass2) are ignored.
z = value
End Sub
End Class
Class Subclass2 : Inherits BaseClass
Dim v As Integer
End Class
What you describe is not casting. Have you ever heard the expression"to cast something in a different light"? It means to look at the same thing in a different way or to make the same thing look different. That is the exact way that the term "cast" is used in programming. When you cast, you do NOT change the type of the object but only the type of the reference used to access the object. If you want to cast from a base type to a derived type then the object you're referring to has to actually be that derived type. If it's not then you're not performing a cast but rather a conversion.
So, why can't you convert an instance of a base type to an instance of a derived type. Well, why would you be able to? Yes, it's something that might save writing a bit of code on occasion but does it actually make sense? Let's say that you have a base type with one property and a derived type that adds another property. Let's also say that that derived type has constructors that require you to provide a value for that second property. You're suggesting that the language should provide you with a way to magically convert an instance of the base class into an instance of the derived class, which would mean it would have to slow you to circumvent that rule defined by the author via the constructors. Why would that be a good thing?
Use System.Reflection to iterate over properties and fields of the base class and apply them to the derived class. This example includes a single public property and single public field, but will also work with multiple private/protected properties and fields. You can paste the entire example into a new console application to test it.
Imports System.Reflection
Module Module1
Sub Main()
Dim p As New Parent
p.Property1 = "abc"
p.Field1 = "def"
Dim c = New Child(p)
Console.WriteLine("Property1 = ""{0}"", Field1 = ""{1}""", c.Property1, c.Field1)
Console.ReadLine()
End Sub
Class Parent
Public Property Property1 As String = "not set"
Public Property Field1 As String = "not set"
End Class
Class Child
Inherits Parent
Public Sub New(myParent As Parent)
Dim fieldInfo = GetType(Parent).GetFields(BindingFlags.NonPublic _
Or BindingFlags.Instance)
For Each field In fieldInfo
field.SetValue(Me, field.GetValue(myParent))
Next
Dim propertyInfo = GetType(Parent).GetProperties(BindingFlags.NonPublic _
Or BindingFlags.Instance)
For Each prop In propertyInfo
prop.SetValue(Me, prop.GetValue(myParent))
Next
End Sub
End Class
End Module
Output:
Property1 = "abc", Field1 = "def"
This solution is automated, so you won't need to change anything when adding or removing properties and fields in the base class.
In general, because of this:
Class TheBase
End Class
Class Derived1 : TheBase
Sub Foo()
End Sub
End Class
Class Derived2 : TheBase
Sub Bar()
End Sub
End Class
Sub Main()
Dim myDerived1 As New Derived1
' cast derived to base
Dim myTheBase = CType(myDerived1, TheBase)
' cast base to derived?
' but myTheBase is actually a Derived1
Dim myDerived2 As Derived2 = CType(myTheBase, Derived2)
' which function call would you like to succeed?
myDerived2.Foo()
myDerived2.Bar()
End Sub
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 have a class Child which extends Test. I want to call a function from Test from Child.
I tried this:
class Test
constructor: ->
#i = 'hello world'
f1: -> console.log #i
f2: -> console.log 'hello'
class Child extends Test
run: ->
Test::f1()
hello = new Child()
hello.run()
When I call hello.run(), it calls Test.f1(), but the result is undefined. It's not setting the static variable #i before it's running Test.f1().
If I switch Test::f1() to Test::f2(), it gives me the correct result.
I need to know how should I make Test's constructor run when I create a new Child() so that #i is defined in Test when I run Test::f1() from Child.run().
Thanks! :D
Here's one way of doing it:
class Test
#i: 'hello world'
#f1: -> console.log #i
f2: -> console.log 'hello'
class Child extends Test
run: ->
Test.f1()
hello = new Child()
hello.run()
Notice, the i variable is static, so it doesn't make sense to set it in the constructor. Also, the f1 method is now static as well.
(I'm not an expert with CoffeeScript, so I'm not sure what the :: syntax is needed for.)
The constructor is being run when you create a new instance of Child. The problem is the way that you're invoking f1.
You don't want to say Test::f1(). You can just say #f1(), since Child is a subclass of Test. These are different in a very important way: Test::f1() does not set this, so when that function requests this.i, it finds only undefined, because this is set to Window (or something ridiculous like that in the browser, not sure if you're running this in Node). Saying #f1() is the same as saying Test::f1.call(this). This is one of the nice things that CoffeeScript's class system lets you do.
Finally, a pedantic note: there are no static variables in the code you've written. i, as you've written it, is an instance variable. Static variables look like this:
class Test
#staticVar = 1234
Or like this:
class Test
# ...
Test.staticVar = 1234
Instance variables look like this:
class Test
fn: ->
#instanceVar = 1234
Or like this:
test = new Test()
test.instanceVar = 1234
Or even like this (for the default value of an instance variable shared among all instances):
Test::instanceVar = 1234
In a similar vein:
When I call hello.run(), it calls Test.f1(), but the result is undefined. It's not setting the static variable #i before it's running Test.f1().
You're never calling Test.f1(); you're calling Test::f1(), which is very different. In the code you've written, there is no Test.f1, only Test.prototype.f1.
I come from a C#/Java background which use a class based OO system and I don't get the JavaScript/CoffeeScript prototype OO system yet. I've written a CoffeeScript class below which allows me to display names for contacts according to a system-side preference. I can only get the class to work by making the joinNonEmpty(stringList, joinText) method belong to the prototype and calling it the way I would call a static method in Java/C# land.
Is there a way I can make this method call using this.joinNonEmpty(...)?
Can you shed some light on why I can reference the firstLastRender, lastFirstRender and firstOrNickThenLast methods in the constructor with this. but it doesn't work from those methods when calling the joinNonEmpty helper?
Does this have something to do with how I'm locating the appropriate method via the preference map?
prefs = displayNameFormat: "FirstOrNickThenLast"
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
# Why does this method have to be static (a class method)?
#joinNonEmpty: (stringList, joinText) ->
nonEmptyStrings = []
for s in stringList
nonEmptyStrings.push(s) if s isnt null and s isnt ""
nonEmptyStrings.join(joinText)
firstLastRender: (contact) ->
# TypeError: Object expected.
joinNonEmpty([contact.firstName, contact.lastName], ' ')
lastFirstRender: (contact) ->
# TypeError: Object doesn't support this method or property
this.joinNonEmpty([contact.lastName, contact.firstName], ', ')
firstOrNickThenLast: (contact) ->
# Works correctly.
DisplayNameRenderer.joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#prefToRenderMap[prefs.displayNameFormat](contact)
contact = firstName: "Jonathan", nickname: "Jonny", lastName: "Appleseed"
dnr = new DisplayNameRenderer()
# => "Jonny Appleseed"
console.log dnr.render(contact)
Thanks for taking the time to answer.
this (AKA #) is determined when the function is called (with exceptions as below). So when you do this:
#prefToRenderMap =
FirstLast: this.firstLastRender
LastFirst: this.lastFirstRender
FirstOrNickThenLast: this.firstOrNickThenLast
You're storing unbound references to the three functions in the #prefToRenderMap instance variable and #prefToRenderMap is itself an object. Then you try to call the methods in your DisplayNameRenderer instance like this:
#prefToRenderMap[prefs.displayNameFormat](contact)
and everything falls apart because the methods are called in the wrong context and # isn't what they're expecting it to be. If prefs is 'FirstOrNickThenLast' then you're effectively doing this:
#prefToRenderMap.FirstOrNickThenLast(contact)
and # (AKA this) will be #prefToRenderMap inside the firstOrNickThenLast method. But, of course, #prefToRenderMap doesn't have any of the methods that you're trying to call so you get various errors.
One solution is to use the fat arrow (=>) to define the methods:
The fat arrow => can be used to both define a function, and to bind it to the current value of this, right on the spot.
So you could have things like this:
joinNonEmpty: (stringList, joinText) ->
#...
firstLastRender: (contact) =>
#joinNonEmpty([contact.firstName, contact.lastName], ' ')
and everything will work out. Here's a stripped down demo that will also show you your this problem:
http://jsfiddle.net/ambiguous/RAPJw/1/
You could also avoid this problem by referring to the methods by their names. Given a method name in a string, m = 'some_method', you can call that method like this o[m]() in both JavaScript and CoffeeScript and the result will be the same as if you said o.some_method(). A better structure would look more like this:
class DisplayNameRenderer
constructor: ->
#prefToRenderMap =
FirstOrNickThenLast: 'firstOrNickThenLast'
joinNonEmpty: (stringList, joinText) ->
#...
firstOrNickThenLast: (contact) ->
#joinNonEmpty([(if contact.nickname isnt null and contact.nickname isnt "" then contact.nickname else contact.firstName), contact.lastName], ' ')
render: (contact) ->
#[#prefToRenderMap['FirstOrNickThenLast']](contact)
Note the change to the structure of #prefToRenderMap and how it is used in render. And a demo of this approach: http://jsfiddle.net/ambiguous/DFYwu/
As an aside, instead of saying ClassName.class_method() inside an instance method, you can use the constructor property instead: #constructor.class_method(). Also, you usually say #method() or #property rather than this.method() and this.property in CoffeeScript.