renovations
This commit is contained in:
parent
c7d4c7e3ff
commit
e1948130f6
170 changed files with 1496 additions and 1161 deletions
|
@ -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`.
|
||||
|
||||
## Что нам даст разделение доступов?
|
||||
## Итого
|
||||
|
||||
Итак, мы сделали кофеварку с публичными и приватными методами и заставили их корректно работать.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue