renovations

This commit is contained in:
Ilya Kantor 2015-01-14 10:23:45 +03:00
parent c7d4c7e3ff
commit e1948130f6
170 changed files with 1496 additions and 1161 deletions

View file

@ -32,7 +32,7 @@
## Внутренний и внешний интерфейс
В программировании есть чёткое разграничение методов и свойств объекта на две группы:
В программировании мы будем разделять методы и свойства объекта на две группы:
<ul>
<li>*Внутренний интерфейс* -- это свойства и методы, доступ к которым может быть осуществлен только из других методов объекта, их также называют "приватными" (есть и другие термины, встретим их далее).</li>
@ -46,27 +46,13 @@
Но снаружи кофеварка закрыта специальным кожухом, чтобы никто к ним не подобрался. Детали скрыты и недоступны. Виден лишь внешний интерфейс.
**Все, что нужно для пользования объектом -- это внешний интерфейс.**
О внутреннем пользователю вообще знать не обязательно.
[smart header="Между приватным и публичным"]
Приватные свойства полностью закрыты для доступа снаружи, а публичные -- наоборот, полностью открыты. Это крайности, между которыми бывают промежуточные варианты.
<ul>
<li>В языке С++ можно открыть доступ к приватным переменным одного класса -- другому, объявив его "дружественным".</li>
<li>В языке Java можно объявлять переменные, которые доступны всем классам внутри "пакета".</li>
<li>Между объектами можно организовать "наследование" и сделать свойства открытыми только для "наследников", такой вариант доступа называют "защищённым".</li>
</ul>
В этом учебнике будем изучать наследование и защищённые свойства, но позже, а пока сосредоточимся на приватном и публичном доступе... И, конечно, использовать мы будем JavaScript :)
[/smart]
Получив объект, всё, что нужно для пользования им -- это знать внешний интерфейс. О внутреннем же знать вообще не обязательно.
Это были общие слова по теории программирования.
Далее мы реализуем кофеварку на JavaScript с приватными и публичными свойствами. В кофеварке много деталей, мы конечно, не будем моделировать каждый винтик, а сосредоточимся на основных приёмах разработки.
### Шаг 1: публичное и приватное свойство
## Шаг 1: публичное и приватное свойство
Конструктор кофеварок будет называться `CoffeeMachine`.
@ -85,28 +71,28 @@ var coffeeMachine = new CoffeeMachine(100);
coffeeMachine.waterAmount = 200;
```
**Локальные переменные, включая параметры конструктора, являются приватными свойствами.**
**Локальные переменные, включая параметры конструктора, можно считать приватными свойствами.**
В примере выше это `power` -- мощность кофеварки, которая указывается при создании и далее будет использована для расчёта времени кипячения.
К локальным переменным конструктора нельзя обратиться снаружи, но они доступны внутри самого конструктора.
**Свойства, записанные в `this`, являются публичными.**
**Свойства, записанные в `this`, можно считать публичными.**
Здесь свойство `waterAmount` записано в объект, а значит -- доступно для модификации снаружи. Можно доливать и выливать воду в любом количестве.
[smart header="Вопрос терминологии"]
Может возникнуть вопрос -- почему я назвал `power` "приватным свойством", ведь это локальная *переменная*, а никакое не *свойство* объекта?
Далее мы будем называть `power` как "локальной переменной", так и "приватным свойством" объекта.
Здесь небольшой конфликт терминологий.
Это, смотря, с какой стороны посмотреть.
Термины "приватное свойство/метод", "публичное свойство/метод" относятся к общей теории ООП. А их конкретная реализация в языке программирования может быть различной.
Здесь ООП-принцип "приватного свойства" реализован через локальные переменные, поэтому и "локальная переменная" и "приватное свойство" -- правильные термины, в зависимости от того, с какой точки зрения посмотреть -- кода или архитектуры ООП.
Здесь ООП-принцип "приватного свойства" реализован через локальные переменные, поэтому и "локальная переменная" и "приватное свойство" -- правильные термины, в зависимости от того, с какой точки зрения взглянуть -- кода или архитектуры ООП.
[/smart]
### Шаг 2: публичный и приватный методы
## Шаг 2: публичный и приватный методы
Добавим публичный метод `run`, запускающий кофеварку, а также вспомогательные внутренние методы `getBoilTime` и `onReady`:
@ -141,11 +127,11 @@ coffeeMachine.waterAmount = 200;
coffeeMachine.run();
```
**Приватные методы, такие как `onReady`, `getBoilTime` объявляются как вложенные функции.**
Приватные методы, такие как `onReady`, `getBoilTime` могут быть объявлены как вложенные функции.
В результате естественным образом получается, что доступ к ним (через замыкание) имеют только другие функции, объявленные в том же конструкторе.
### Шаг 3: константа
## Шаг 3: константа
Для расчёта времени на кипячение воды используется формула `c*m*ΔT / power`, где:
<ul>
@ -171,7 +157,7 @@ function CoffeeMachine(power) {
// расчёт времени для кипячения
function getBoilTime() {
return this.waterAmount * WATER_HEAT_CAPACITY * 80 / power;
return this.waterAmount * WATER_HEAT_CAPACITY * 80 / power; // ошибка!
}
*/!*
@ -181,7 +167,7 @@ function CoffeeMachine(power) {
}
this.run = function() {
setTimeout(onReady, getBoilTime());
setTimeout(onReady, getBoilTime());
};
}
@ -194,9 +180,9 @@ coffeeMachine.run();
Удельная теплоёмкость `WATER_HEAT_CAPACITY` выделена большими буквами, так как это константа.
**Внимание, при запуске кода выше в методе `getBoilTime` будет ошибка. Как вы думаете, почему?**
Внимание, при запуске кода выше в методе `getBoilTime` будет ошибка. Как вы думаете, почему?
### Шаг 4: доступ к объекту из внутреннего метода
## Шаг 4: доступ к объекту из внутреннего метода
Внутренний метод вызывается так: `getBoilTime()`. А чему при этом равен `this`?... Как вы наверняка помните, в современном стандарте он будет `undefined` (в старом -- `window`), из-за этого при чтении `this.waterAmount` возникнет ошибка!
@ -311,11 +297,11 @@ coffeeMachine.run();
Теперь `getBoilTime` получает `self` из замыкания.
**Конечно, чтобы это работало, мы не должны изменять `self`, а все приватные методы, которые хотят привязаться к текущему объекту, должны использовать внутри себя `self` вместо `this`.**
**Конечно, чтобы это работало, мы не должны изменять `self`, а все приватные методы, которые хотят иметь доступ к текущему объекту, должны использовать внутри себя `self` вместо `this`.**
Вместо `self` можно использовать любое другое имя переменной, например `var me = this`.
## Что нам даст разделение доступов?
## Итого
Итак, мы сделали кофеварку с публичными и приватными методами и заставили их корректно работать.