I have a class like this:
class Cow
#feet : 4
constructor: (#name) ->
bes = new Cow "Bessie"
The question is, is it possible to access feet only given bes?
You can use the JavaScript constructor property to get at the class and there you will find your feet:
class Cow
#feet: 4
constructor: (#name) ->
class HexaCow extends Cow
#feet: 6
bes = new Cow('Bessie')
pan = new HexaCow('Pancakes')
alert(bes.constructor.feet) # 4
alert(pan.constructor.feet) # 6
Demo: http://jsfiddle.net/ambiguous/ZfsqP/
I don't know of any special CoffeeScript replacement for constructor though.
Related
As someone who worked more in Java, I am having a bit of difficulty wrapping my head around polymorphic references to class attributes in Python.
What I would like to do is have a method in the base class which modifies a "static" variable (aka class attribute) of the base class, but when calling the method from the derived class, for the method to modify the class attribute of the derived class, not the base class. Note, I am NOT overriding the method in the derived class.
For example, I have something like:
class BaseClass:
itemList = []
def addItem(thing):
BaseClass.itemList.append(thing)
class Child1(BaseClass):
pass
class Child2(BaseClass):
pass
...
Child1.addItem("foo")
Child2.addItem("bar")
print(str(Child1.itemList))
I'd like: "foo"
I get: "foo, bar"
Now, I understand that because of "BaseClass.itemList.append(thing)", it will reference the class attribute of the base class.
Put another way, is there a way to avoid saying "BaseClass.itemList", but keep it static, or do I need to instead override the method in each of the child classes?
You can have a "static" class variable that can be changed by every instance of the class:
class BaseClass:
itemList = []
def addItem(self, thing):
self.itemList.append(thing)
class Child1(BaseClass):
itemList = []
class Child2(BaseClass):
itemList = []
# each class has its own "itemList"
# now we can instantiate each class and use the different itemLists:
c1 = Child1()
c1.addItem("foo")
c2 = Child2()
c2.addItem("bar")
c3 = Child1()
c3.addItem("foo2")
print(str(Child1.itemList)) # prints: ['foo', 'foo2']
print(str(Child2.itemList)) # prints: ['bar']
I want to define multiple properties of different "classes"/prototypes when creating a new object.
class Animal
constructor: (#name, #temperament, #diet) ->
#methods that use those properties
eat: (food) ->
console.log "#{name} eats the #{food}."
class Bird extends Animal
constructor: (#wingSpan) ->
#methods relating only to birds
class Cat extends Animal
constructor: (#tailLength) ->
#methods relating only to cats
myCat = new Cat ("long", {"Mr. Whiskers", "Lazy", "Carnivore"})
I'm doing something wrong, though. Only the constructor for Cat seems to get any properties.
Also, is there a way to define them with key/value pairs?
Ideally, I'd write something like myCat = new Cat (tailLength: "long", name: "Mr. Whiskers", temperament: "Lazy"), so that I can define properties that aren't in order and it would fall back to a default if I failed to define a property like "diet".
My understanding is that prototype methods will bubble up, so if I call myCat.eat 'cat food', the output should be "Mr. Whiskers eats the cat food." But... it can't be since the Animal class isn't getting the new Cat's name.
Just use {} if you mean "an object".
class Animal
constructor: ({#name, #temperament, #diet}) ->
#methods that use those properties
eat: (food) ->
console.log "#{#name} eats the #{food}."
class Bird extends Animal
constructor: ({#wingSpan}) ->
super
#methods relating only to birds
class Cat extends Animal
constructor: ({#tailLength}) ->
super
#methods relating only to cats
myCat = new Cat(tailLength: "long", name: "Mr. Whiskers", temperament: "Lazy", diet: "Carnivore")
I have two coffeescript classes something like this. In the base view model I have a method that I want to override in the child that inherits from the base view model.
class exports.BaseViewModel
constructor: () ->
someBaseMethod: =>
console.log "I'm doing the base stuff"
class ChildViewModel extends BaseViewModel
constructor: () ->
someBaseMethod: =>
#doSomethingFirst()
super #someBaseMethod()
This isn't working as is because the line super #someBaseMethod() calls itself creating an infinite loop.
Is it possible to achieve what I want here?
Yes, call super just like it was a function (it represents a reference to the superclass version of the method you're in):
class ChildViewModel extends BaseViewModel
constructor: ->
someBaseMethod: =>
#doSomethingFirst()
super()
How can I find that class of an object once it has been instantiated?
class Cat
constructor: (#name) ->
class Dog
constructor: (#name) ->
cat = new Cat "Kitty"
dog = new Dog "Doggy"
if (cat == Cat) <- I want to do something like this
Just change the == to instanceof
if(cat instanceof Cat)
If you wanted to know the type name of a particular object (which is what I was just looking for when I found this question), you can use the syntax {object}.constructor.name
for example
class Cat
constructor: (#name) ->
class Dog
constructor: (#name) ->
cat = new Cat()
dog = new Dog()
console.log cat.constructor.name
console.log dog.constructor.name
which will output
Cat
Dog
The way to do this is to check the type of an object using either
instanceof
or
typeof
i.e.
if (obj instanceof Awesomeness){
//doSomethingCrazy();
}
Just as in JavaScript, Coffee Script does not provide any abstraction over these functions
AFAIU, the general solution would be using #constructor - Useful when you don't know or don't want to specify the class name.
There was even a discussion regarding making ## a shortcut for it.
I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.