Что такое объектно-ориентированное программирование?
Объектно-ориентированное программирование (ООП) - это такой подход к программированию, в котором программа представляет собой совокупность взаимодействующих между собой объектов. Мы уже знаем, что класс - это свой тип данных, описывающий, как устроен каждый объект; объекты - это конкретные экземпляры класса. Однако ООП подразумевает нечто большее, чем просто то, что каждая переменная является объектом. Существует 4 основных принципа ООП:
- Инкапсуляция
- Наследование
- Полиморфизм
- Абстракция
Они сложные, но очень мощные. Их надо знать обязательно. Тем более, что эти принципы общие для всех Си-подобных языков.
Сейчас мы разберём первый из них.
Модификатор readonly
Пусть мы хотим сделать забег животных. У каждого животного будет кличка, чтобы можно было их различать. Животные бегут по прямой, то есть, у каждого из них есть одна координата - X. У каждого животного есть скорость Speed - за одну условную единицу времени координата X увеличивается на Speed. Все животные бегут только в одном направлении, то есть, X не может уменьшаться. Скорость каждого животного обозначается при его создании и не может изменяться.
Сделаем класс Animal ("Животное"). У каждого животного будет кличка Name, а значит, в классе будет поле Name:
Разумеется, кличка не должна меняться после создания животного. Но сейчас кто-нибудь может нечаянно её изменить:
Чтобы исправить это, добавим к полю Name модификатор readonly ("только чтение"):
Поля, помеченные readonly, могут устанавливаться только при создании объекта и потом уже не могут меняться. Попытка изменить такое поле приведёт к ошибке:
Уберём попытку изменить имя:
Всё станет хорошо. Зачем это нужно, мы разберём чуть ниже.
Аналогичным образом добавьте скорость и сделайте, чтобы её нельзя было менять после создания животного.
Что такое инкапсуляция?
У животного будут X и Speed, а значит, в классе Animal будут такие поля. Какие действия можно делать над животным? Сдвинуть его за единицу времени на Speed. Значит, в классе будет метод Move():
Но сейчас кто-нибудь может сломать работу класса, напрямую задав координату X:
Здесь readonly уже не поможет, потому что X должна меняться при вызове Move().
Чтобы никто нечаянно не мог влезть в логику работы класса, поля и методы класса можно защищать. Есть такие модификаторы доступа, которые можно навешивать на поля и методы:
- public - доступно везде
- protected - недоступно снаружи класса, но доступно в классах-наследниках (разберём это в теме "Наследование")
- private - недоступно снаружи и в классах-наследниках. Доступно только изнутри класса.
Каждый следующий модификатор доступа более строг, чем предыдущий. Это основные модификаторы доступа, они есть во всех си-подобных языках. Кроме них конкретно в C# есть ещё другие, но они почти не используются. См. https://yandex.ru/search/?text=c%23+модификаторы+доступа
Заменим в определении поля X public на private. Теперь поле X не видно снаружи класса:
Так что никто не может нечаянно испортить X. Вот это, когда мы делаем поля и методы невидимыми снаружи, как бы заключаем их в капсулу, и называется инкапсуляцией. Инкапсуляция защищает логику класса от вмешательств извне. Класс превращается в "чёрный ящик", которым другие программисты могут пользоваться, не зная, как он устроен внутри и изучив только public-поля и методы. То есть, для пользования классом больше не нужно изучать код внутри него, что упрощает командную работу.
Но теперь мы не можем узнать координату животного, так как X не виден снаружи. Поэтому нам придётся сделать метод, который будет выдавать наружу значение X:
Итак, чтобы воспользоваться нашим классом, другим программистам больше не нужно знать, по каким правилам меняется X - им достаточно знать публичные поля и методы: что конструктор принимает на вход кличку и скорость, что есть метод Move(), который нужно вызывать по прошествии единицы времени, и что есть метод GetX(), который позволяет узнать координату. Всё упростилось - чтобы устроить забег, больше не нужно знать, как работают X, Speed и подобное!
Найдите животное, которое выиграло забег, и распечатайте сообщение в формате "Победитель: {Имя}".
Предупреждения и улучшения Rider
Вернёмся в класс. Там горит несколько улучшений.
"Поле 'Speed' может быть сделано приватным". Подумаем - правда ли стоит сделать его приватным? Оно не используется нигде снаружи и не будет использоваться, по крайней мере, для записи. Всегда, когда можно, надо использовать более строгий модификатор доступа. Можно либо вручную заменить public на private, либо поставить туда каретку для ввода текста и нажать на лампочку:
Теперь название поля Speed подсветится жёлтым:
"Имя 'Speed' не соответствует правилу 'Поля экземпляров (private)'. Предлагаемое имя - '_speed'". По стилю кода, приватные поля принято называть, начиная с подчёркивания и с маленькой буквы. Публичные поля - с большой (без подчёркивания). Исправляем таким же образом:
Исправьте также и X.
А вот применять "Преобразовать в первичный конструктор" здесь нет особого смысла - из кода получится каша. Попробуйте и верните назад через Ctrl + Z.
Далее
Свойства, геттеры и сеттеры - https://dzen.ru/a/aaAKjosrTz0TTFNA?share_to=link
Оглавление - https://dzen.ru/a/aXisxwt_Mnz2qTjs?share_to=link