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.
Related
I'm not sure if the title says it all.
What I'm trying to do is to have a super class (or a more or less abstract class) which then is used by another class which is extending itself from the super class.
Now what I did was to create a simple script:
class Animal
constructor: (#name, #sound) ->
setSound: (#sound) ->
sound: ->
alert "#{#sound}!!!"
name: ->
alert "#{#name}"
class Dog extends Animal
constructor: (#name) ->
#setSound "Woof"
doggy = new Dog "Max"
doggy.sound()
As you can see - this is just a crappy example but what happens is, when I now call doggy.sound() I get an TypeError in return.
You can see this script in action here: http://jsfiddle.net/zrVZb/1/
Am I doing something wrong or is this even a bug in coffeescript?
edit: I just saw, that it is contructor and not construct. But now I'm getting the TypeError instead.
Thanks
Your method is called sound. But then you pass an attribute with the same name, which overwrites this method. Try renaming your sound method into makeSound :
http://jsfiddle.net/V7Dx8/1/
Please let me know how to make the following bit of code work as intended. The problem is that the Scala compiler doesn't understand that my factory is returning a concrete class, so my object can't be used later. Can TypeTags or type parameters help? Or do I need to refactor the code some other way? I'm (obviously) new to Scala.
trait Animal
trait DomesticatedAnimal extends Animal
trait Pet extends DomesticatedAnimal {var name: String = _}
class Wolf extends Animal
class Cow extends DomesticatedAnimal
class Dog extends Pet
object Animal {
def apply(aType: String) = {
aType match {
case "wolf" => new Wolf
case "cow" => new Cow
case "dog" => new Dog
}
}
}
def name(a: Pet, name: String) {
a.name = name
println(a +"'s name is: " + a.name)
}
val d = Animal("dog")
name(d, "fred")
The last line of code fails because the compiler thinks d is an Animal, not a Dog.
You should create companion objects with apply method for each subclass of Animal instaed of Animal trait. Also, it is considered a bad practice to use mutable field like you did with name.
You can do that, without changing anything else :
val d = Animal("dog").asInstanceOf[Dog] //> d : Test.Dog = Test$$anonfun$main$1$Dog$1#1030dda
name(d, "fred") //> Test$$anonfun$main$1$Dog$1#1030dda's name is: fred
But, i don't think it's a very good idea...
I don't want to sound rude but the compiler is right about assuming that d is an Animal because that's what the Animal.apply method returns.
As already pointed out you could force the type of d with an explicit cast but it simply wouldn't be type safe. It would be leveraging your knowledge about the method implementation as a programmer, which will eventually become a source of bugs as your codebase grows and you possibly change previous code in unexpected ways.
If you need to call a Pet method then you would better use a factory method that creates Pet objects, or at least check the object type before doing the type cast, using
if (d.isInstanceOf[Pet]) name(d.asInstanceOf[Pet], "Fred")
Or better still, using pattern matching
val d = Animal("dog")
d match {
case p: Pet => name(p, "fred")
case _ =>
}
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've created a singleton class which I want to extend. It (half) works in that it only creates a single instance of the class, but properties added to the subclass are undefined. Here is the original singleton:
class Singleton
_instance = undefined
#getInstance: ->
if _instance is undefined
console.log 'no instance exists, so create one'
_instance = new _Singleton()
else
console.log 'an instance already exists.'
class _Singleton
constructor: ->
console.log 'new singelton'
module.exports = Singleton
And here is the subclass:
Singleton = require('./singleton')
class Stinky extends Singleton
constructor: ->
var1 : 'var1'
module.exports = Stinky
Now if I use the following in my node app:
Stinky = require './stinky'
thing1 = Stinky.getInstance()
thing2 = Stinky.getInstance()
console.log "Thing var1: #{thing1.var1}"
the getInstance() method behaves as expected, but var1 is undefined. If I do this same thing on non singleton classes they work fine. Thanks.
I trimmed your code down a bit. Here are the 2 remaining classes:
class Singleton
#_instance: null
#getInstance: ->
#_instance or= new #( arguments... )
class Stinky extends Singleton
constructor: ( #num ) ->
thing1 = Stinky.getInstance( 1 )
thing2 = Stinky.getInstance( 2 )
console.log( thing1.num, thing2.num )
I made the following changes:
Merged Singleton and _Singleton
Changed _instance to #_instance so that it would be attached to Singleton rather than its prototype
Added arguments splat in getInstance (in case arguments are needed)
Pointing getInstance() to extended object rather than Singleton
In this example, I used 2 different numbers to ensure that the 2nd constructor was never called.
I see how you're using the _Singleton class to try to simulate a private class, but unfortunately I don't think you can use it in this case.
Here is some code that works:
class Singleton
_instance = undefined
constructor: ->
console.log 'new singleton'
#getInstance: ->
if _instance is undefined
console.log 'no instance exists, so create one'
_instance = new #()
else
console.log 'an instance already exists.'
_instance
class Stinky extends Singleton
constructor: ->
console.log 'Stinky constructor'
#var1 = 'var1'
thing1 = Stinky.getInstance()
thing2 = Stinky.getInstance()
console.log "Thing var1: #{thing1.var1}", thing1, thing2
I removed the Node.js (require) code, but adding that in should be straightforward. The main difference is that the instance my code is creating is an instance of # or this. Doing so will make sure your constructor is called first then continue up the parent chain. Your code was explicitly creating an instance of _Singleton so your Stinky constructor was never being called. Another minor issue that you would have eventually noticed was that your getInstance method was not actually returning a instance of _instance.
I hope this helps,
Sandro
I'm not sure what the goal is, but you can achieve the same result by making Singleton a real singleton (a plain object):
Singleton =
doNothing: ->
# ...
doMoreNothing: ->
# ...
class Stinky
constructor: ->
#var1: 'var1'
getInstance: ->
return Singleton
It doesn't make much sense for Singleton to have a method that returns itself.
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.