Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between reopen() and reopenClass() in Ember.js

I got confused while I was reading the documentation on emberjs.com http://emberjs.com/documentation/#toc_reopening-classes-and-instances

On the page above, it explains like this.

Person.reopen({
    // override `say` to add an ! at the end
    say: function(thing) {
    this._super(thing + "!");
    }
});

As you can see, reopen is used to add properties and methods to an instance. But when you need to create class method or add the properties to the class itself you can use reopenClass.

Person.reopenClass({
    createMan: function() {
    return Person.create({isMan: true})
    }
});

Person.createMan().get('isMan') // true

although the explanation says "reopen is used to add properties and methods to an instance.", I think both example shown above are talking about how to create class method or add the properties to the class itself, not to the instance.

Am I misunderstanding what it says? I'm not an experienced programmer, so I might be misunderstood...

please explain when to use reopen and reopenClass if I'm misunderstood.

Thanks in advance!

like image 471
crzyonez777 Avatar asked Dec 24 '12 22:12

crzyonez777


2 Answers

The documentation doesn't explain this very well, but it is a very tricky subject.

BTW, it now lives at: http://emberjs.com/guides/object-model/reopening-classes-and-instances/

One of the problems with talking about Object-Oriented Programming is that it's often explained like this: - Objects are Objects. Objects are instances of a class. - Classes are Objects. - Instances are Objects, and have a Class.

This explanation doesn't help anyone at all, and seems to be a recursive problem (ie there's no end to the referencing... An Object is an Instance of a Class which is an Object... (repeat)).

I prefer to reason in the following way:

When people write code, they often describe classes and instances. Classes are a type of thing. Fruit is an example of a class. We're not talking about a particular thing here, we're talking about a whole "class" of things (hence the name).

Note that it's not a real class. It's only real when it's "live" and "in memory in the computer". Until then, it's a description of a class. Usually when people write code, they write text in a text file, and that's just description of the real code inside the computer that happens when the computer interprets or compiles it into machine code.

The tricky bit comes when you realise that a class is actually itself a description, too. It's a description of a whole range of potentially real objects.

In the computer, when you create "an apple", that's an instance. It's also an object. Its class is Apple, which in a computer is a real live object, too. When we talk about Apple, that's an idea. It doesn't exist in reality, but for a computer to use something it must make it exist in its reality, so "Apple" is a concrete, real object, even though it's also an abstraction.

I think the last point is what gets people confused about objects. Classes are abstractions, but in order for the computer to talk and reason about them, they have to be made real. So, we decide... "class means abstract, instance means real"...

The trouble is, we have inheritance... which brings in the idea of layers of abstraction... so in our fruit model, you have the particular apple in front of you, which is also a Fruit, and Fruit is also a Food. In reality, Food doesn't actually exist as a thing or set of things, unless we say "this food, this apple", or "all the food in the world", or "your mum's lasagne", then it's an abstract idea...

So, in our object oriented computer, we say "define Food which is a kind of Object, now define Fruit which is a kind of Food, now define Apple which is a kind of Fruit, now define this apple, which is a kind of Apple".

Now that means: - Object is Food's class, and Food is an instance of Object, and Food is also itself a class! - Food is Fruit's class, and Fruit is an instance of Food, and Fruit is itself also a class! - Fruit is Apple's class, and Apple is an instance of Fruit, and Apple is also itself a class! - Apple is your apple's class, and your apple is an instance of Apple (and therefore also of Fruit, Food and Object!). However, it's NOT a class, it's just an object.

To reason about your apple, we'd say it's an object (note the lowercase o), it's also an Apple, and a Fruit and a Food, and... here's the kicker.. it's also an Object.

So now hopefully we're in a position where we can understand that your apple is an object, an instance (of Apple, Fruit, Food & Object), an Apple, a Fruit, a Food and an Object, but it's not a class.

So... if you add an instance method to a class, then it won't be available on the class, but it'll be available on all instances of that class. If you add a class method, it'll be available on that class (and sub-classes). So if you add an instance method to Apple, then all instances of apple will be able to run that method. If you add a method to only your apple, though, then only your apple will have that method. My apple won't. If you add a class method to Apple, then only the Apple class will be able to run that method (which, conveniently you can also access through all its instances). Class methods are for things which don't change PARTICULAR instances. Instance methods are for things which DO change PARTICULAR instances (generally). Same thing goes for properties/attributes. You wouldn't create a class method on the Apple class called "Apple colour" because that sounds like it relates to particular Apples (ie instances). Hopefully that clears things up a bit :)

like image 125
Julian Leviston Avatar answered Nov 01 '22 12:11

Julian Leviston


After I experimented with reopen()and reopenClass(), I figured out the difference between them.

Here is the result from my experiment.

var Person = Ember.Object.extend({

    name:"",
    alive:true,
    sayHi:function(){
        alert("hi");
    }

});

Person.reopenClass({
    age:30,

    sayHo:function(){
    alert("ho");
}   

});

Person.reopen({
height:180,
sayYo:function(){
    alert("yo");
}
})

var person = Person.create({
    name:"Tom"
});


//person.reopenClass();//error!!

person.reopen({
    sayWhat:function(){
        alert("what!?");
    },

    weight:100

});

console.log(Person.alive);//undefined
console.log(Person.age);//30
console.log(Person.height);//undefined
console.log(Person.weight);//undefined

console.log(person.alive);//true
console.log(person.name);//Tom
console.log(person.height);//180
console.log(person.weight);//100

person.sayHi();//it works

//person.sayHo();//it doesn't work
Person.sayHo();//it works

person.sayYo();//it works
//Person.sayYo();//it doesn't work

//Person.sayWhat();//it doesn't work
person.sayWhat();
like image 2
crzyonez777 Avatar answered Nov 01 '22 13:11

crzyonez777