Разница между reopen() и reopenClass() в Ember.js

Я запутался, когда читал документацию на emberjs.com http://emberjs.com/documentation/#toc_reopening-classes-and-instances

На приведенной выше странице это объясняется следующим образом.

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

Как вы можете видеть, повторное открытие используется для добавления свойств и методов в экземпляр. Но когда вам нужно создать метод класса или добавить свойства к самому классу, вы можете использовать reopenClass.

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

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

хотя объяснение говорит, что "повторное открытие используется для добавления свойств и методов в экземпляр". Я думаю, что оба примера, показанные выше, говорят о том, как создать метод класса или добавить свойства к самому классу, а не к экземпляру.

Неужели я не понимаю, что он говорит? Я не опытный программист, поэтому меня могут неправильно понять...

Пожалуйста, объясните, когда использовать повторно открыть и повторно открыть кластер, если меня не поняли.

Спасибо заранее!

Ответы

Ответ 1

Документация не очень хорошо объясняет это, но - очень сложный вопрос.

Кстати, теперь он живет: http://emberjs.com/guides/object-model/reopening-classes-and-instances/

Одна из проблем, связанных с объектно-ориентированным программированием, заключается в том, что она часто объяснялась следующим образом: Объекты - объекты. Объекты - это экземпляры класса. - Классы - это объекты. - Экземпляры - это объекты и имеют класс.

Это объяснение вообще не помогает любому и кажется рекурсивной проблемой (т.е. нет ссылки на ссылку... Объект - это экземпляр класса, который является объектом... (повтор)).

Я предпочитаю рассуждать следующим образом:

Когда люди пишут код, они часто описывают классы и экземпляры. Классы - это вещь. Фрукты - пример класса. Мы здесь не говорим о конкретной вещи, мы говорим о целом "классе" вещей (отсюда и название).

Обратите внимание, что это не настоящий класс. Это только реально, когда он "живет" и "в памяти на компьютере". До тех пор это описание класса. Обычно, когда люди пишут код, они пишут текст в текстовом файле и это просто описание реального кода внутри компьютера, которое происходит, когда компьютер интерпретирует или компилирует его в машинный код.

Трудный бит приходит, когда вы понимаете, что класс на самом деле тоже описание. Это описание целого ряда потенциально реальных объектов.

В компьютере, когда вы создаете "яблоко", это экземпляр. Это тоже объект. Его классом является Apple, который в компьютере также является настоящим живым объектом. Когда мы говорим об Apple, это идея. Это не существует на самом деле, но для того, чтобы компьютер использовал что-то, он должен сделать его существующим в своей реальности, поэтому "Яблоко" представляет собой конкретный, реальный объект, хотя это также абстракция.

Я думаю, что последний момент - это то, что заставляет людей путать объекты. Классы - это абстракции, но для того, чтобы компьютер мог говорить и рассуждать о них, они должны быть реальными. Итак, мы решаем... "класс означает абстрактный, экземпляр означает реальный"...

Беда в том, что у нас есть наследство... которое приносит идею слоев абстракции... так что в нашей модели фруктов у вас есть конкретное яблоко перед вами, которое также Фрукты, и Фрукты также являются Пищей. На самом деле, Пища фактически не существует как вещь или множество вещей, если мы не говорим "это пища, это яблоко" или "вся еда в мире" или "ваша мама-лазань", то это абстрактная идея...

Итак, на нашем объектно-ориентированном компьютере мы говорим: "Определите Пищу, которая является своего рода Объектом, теперь определите Fruit, который является своего рода Пищей, теперь определите Apple, которая является своего рода Плодом, теперь определите это яблоко, которое своего рода Apple".

Теперь это означает: - Объект - это класс продуктов, а Food - это экземпляр объекта, а Food также является классом! - Пища - это класс Фруктов, а Фрукты - пример Пищи, а Фрукты - это тоже класс! - Fruit - это класс Apple, а Apple - это пример Fruit, а Apple также является классом! Apple - ваш класс Apple, а ваше яблоко - это пример Apple (и, следовательно, также Fruit, Food and Object!). Тем не менее, это НЕ класс, это просто объект.

Чтобы рассуждать о вашем яблоне, мы бы сказали, что это объект (обратите внимание на нижний регистр o), это также Apple, и фрукты и еда, и... вот кикер.. это тоже объект.

Итак, теперь мы надеемся, что мы в состоянии понять, что ваше яблоко - это объект, экземпляр (Apple, Fruit, Food and Object), Apple, фрукты, еда и объект, но это не класс.

Итак... если вы добавите метод экземпляр для класса, то он не будет доступен в классе, но он будет доступен для всех экземпляров этого класса. Если вы добавите метод класса, он будет доступен в этом классе (и подклассах). Поэтому, если вы добавите метод экземпляра в Apple, тогда все экземпляры apple смогут запустить этот метод. Однако, если вы добавите метод только к вашему яблоку, то только ваш яблоко будет иметь этот метод. Мое яблоко не будет. Если вы добавите метод класса в Apple, тогда только класс Apple сможет запустить этот метод (который, кстати, вы также можете получить доступ ко всем его экземплярам). Методы класса предназначены для вещей, которые не изменяют экземпляры ОСОБЕННЫЕ. Методы экземпляра для вещей, которые меняются ОСОБЕННОэкземпляры (обычно). То же самое касается свойств/атрибутов. Вы бы не создали метод класса в классе Apple под названием "Цвет Apple", потому что это звучит так, как будто оно относится к конкретным Ябменам (например, экземплярам). Надеюсь, это немного очистит:)

Ответ 2

После того, как я экспериментировал с reopen() и reopenClass(), я понял разницу между ними.

Вот результат моего эксперимента.

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();