Попытка собрать и связать между собой разные сведения о понятии объекта в ООП.
Сначала были структуры:
struct point_xyz
{
int x;
int y;
int z;
};
Но по мере роста размера и сложности программ возникло новое понятие — объект.
Собственно, можно из всего множества определений объекта выделить два понятия:
а) объект как «данные и методы работы с ними» и б) «объект как сущность (организм)».
Первый вариант понятия объекта наиболее распространен, второй встречается реже.
Появились основные принципы ООП (выделяют от 3 и более принципов):
1) Инкапуляция
2) Наследование
3) Полиморфизм
4) Абстракция
5) Посылка сообщений
6) Повторное использование
Главный тут самый первый принцип — инкапсуляция.
Но будем идти по порядку. Для примеров далее будем использовать Java, как наиболее типичный представитель мира ООП.
I) Структура:
public class Person {
public String fistName;
public String secondName;
public String middleName;
}
Так, конечно, мало кто пишет. Минусы очевидны — любое значение меняется извне без каких либо ограничений. Об объекте речи быть не может. Здесь никакой инкапсуляции нет — это структура. Данные без коробочки.
Но есть и плюсы — объем кода. Никаких мешающих взгляду геттеров и сеттеров. Например, структуры можно использовать в виде внутренних классов, получая доступ к полям без геттеров и сеттеров, спасая код от захламления.
Посмотрите как сделан внутренний класс Node. По-моему, очень красиво.
Можно переделать класс Person и использовать его как внутренний в каком-то другом классе:
public class Foo {
private class Person {
private String fistName;
private String secondName;
private String middleName;
}
}
II) «Улучшенная структура» — это структура с геттерами и сеттерами.
public class Person {
private String fistName;
private String secondName;
private String middleName;
public String getFistName() {
return fistName;
}
public void setFistName(String fistName) {
this.fistName = fistName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
}
Можем ли мы назвать это объектом? С одной стороны мы обеспечили сокрытие полей класса. Теперь к ним можно получить доступ из других классов только через методы. Это во многих случаях дает дополнительную гибкость. Например, можно отсеивать невалидные значения.
Формально определение «данные и методы работы с ними» соблюдено. С другой стороны, инкапсуляция подразумевает целостность данных. Данные, заключенные в «коробочку», должны быть целостны, какие бы извне методы не вызывались. А у нас при вызове сеттеров в какой-то момент может получится что целостность будет нарушена. Например, будем переименовывать Ивана Ивановича Иванова в Елену Петровну Сидорову. После вызова первого сеттера получим Елену Ивановича Иванова.
Где такие вещи используются? Везде. К сожалению. Это глупая коробочка для данных, во многих случаях не поддерживающая их целостность.
III) Объект с инкапсуляцией
public class Person {
private final String fistName;
private final String secondName;
private final String middleName;
public Fio(String fistName, String secondName, String middleName) {
this.fistName = fistName;
this.secondName = secondName;
this.middleName = middleName;
}
public String getFistName() {
return fistName;
}
public String getSecondName() {
return secondName;
}
public String getMiddleName() {
return middleName;
}
}
Ну теперь по крайней мере объект всегда в целостном состоянии. Елену Ивановича Иванова не получим в качестве промежуточного результата. Кроме того, объект стал не изменяемым — что огромный плюс, в том числе для многопоточной работы. Первому определению объекта соответствуем. Это очень умная коробочка для данных — она поддерживает их целостность. Но это все равно коробочка.
IV) Объект-организм
public class Person {
private String fistName;
private String secondName;
private String middleName;
public Person(String fistName, String secondName, String middleName) {
this.fistName = fistName;
this.secondName = secondName;
this.middleName = middleName;
}
public void sayName(PrintStream printStream) {
if (middleName == null) printStream.print(fistName + " " + secondName);
else printStream.print(fistName + " " + middleName + " " + secondName);
}
}
Убираем геттеры, сеттеры. Объект становится сущностью, сам осуществляет целостную обработку данных. Мы его лишь «просим». У коробочки с данными появились ножки.
Теперь Вы знаете разгадку первой картинки и где на ней объект.
Автор: nemavasi