[МУЗЫКА] На сегодняшней лекции мы поговорим подробнее об объектно-ориентированном программировании. На прошлой лекции мы его слегка упомянули, и теперь пришло время разобраться, что же это такое, более подробно. Так, как я уже говорил, идеи ООП — объектно-ориентированного программирования — начали массово внедряться в языки ну где-то годов с 80-х. И Python, естественно, когда он появился, уже позже, в 90-х годах и развивался еще позже, Python 3 появился уже в 2000-х, конечно же эти идеи ООП впитал. Появились они за счет того, что выросли ресурсы вычислительные, и можно было позволить себе некоторые накладные расходы дополнительные, которые возникают из-за сложной структуры программ, взамен на более простое написание кода. Ну, грубо говоря, программисты стали стоить дороже, чем компьютеры, на которых эти программы выполняются. Для чего удобно ООП? Как я уже говорил, у нас есть объекты, которые живут где-то в памяти и проявляют активность, когда вызывают какой-то метод для них. Ну например, у нас есть объект строка. Стандартный объект языка Python. Он лежит себе, и пока мы ничего с этой строкой сделать не хотим, просто занимает память. Если же мы хотим что-то сделать со строкой, то мы пишем название этого объекта, точку и какой метод мы хотим применить. Вот примерно так и должны вести себя объекты. Как я уже говорил, когда ООП появилось, хотелось весь мир приспособить под него, казалось, что это решит абсолютно все проблемы. Но на самом деле не весь мир под него приспосабливается, по крайней мере, не всегда это бывает удобно. Ну например, вы смогли пройти восемь занятий, практически не пользуясь объектно-ориентированным программированием. Ну, не считая вызова методов для стандартных классов. И вполне себе справлялись, как и справлялись люди до 80-х годов. ООП удобно, когда вы хотите наследовать какие-то признаки, то есть вы все объекты хотите уложить в какую-то древовидную иерархию. На самом верху у вас нечто абстрактное. Ну давайте попробуем написать там... мячики. Вот у нас на самом верху абстрактный мячик, он обладает некоторыми свойствами, общими для всех мячиков: что это там сфера, ну и, наверное, все. Больше никаких общих свойств у мячика нет. И затем от него наследуются там разные мячики. Наследуется какой-то шар, может быть, потом от него наследуется стеклянный шар, стальной шар, и какие-то свойства меняются в процессе. Или это мяч для игры, наследуется там мяч для игры, от него, в свою очередь — волейбольный, баскетбольный и т.д. Вот в такой иерархии мы можем рассчитывать на то, что мы можем воспользоваться просто всеми свойствами и методами нашего предка. Например, для футбольного мячика не надо писать, что он имеет сферическую форму, поскольку он уже пронаследован от сферического какого-то абстрактного объекта. Таким образом, если удается описать такую структуру, когда у нас все хорошо ложится, и действительно объекты немного отличаются от своего абстрактного предка или конкретного предка в этом дереве... Ну, дерево можно представить себе, как генеалогию, где родители и дети. Такая терминология применяется. И вот если объект так можно написать, то тогда действительно ООП подходит хорошо. Но далеко не все объекты укладываются в древовидную структуру, ну, в некоторых языках она может быть даже не древовидной, да и даже в Python можно попробовать пронаследовать сразу от двоих. Но тем не менее, это уже довольно странные вещи, и они совсем непонятны. Давайте же подробно перейдем конкретно к трем главным словам ООП: это инкапсуляция, это наследование и это полиморфизм. В целом я обо всем этом рассказал. Но давайте подробнее. Что такое инкапсуляция? Это помещение в капсулу, ну, от латинского in capsula. То есть мы все наши данные, все наши методы работы с ними помещаем в одно место. Мы уже сталкивались со странностями, ну например, функция len для разных объектов. Если бы это было не ООП (ну, мы посмотрим, как она устроена в сегодняшних следующих видеофрагментах), если бы это было не ООП, то нам пришлось бы лазить каждый раз при создании нового типа данных в исходный текст функции len и что-то в нее вписывать. Она бы разрослась и была бы нечитаема, и неподдерживаемо это все было бы, то есть это очень сложно было бы распространить. Когда мы обернули объект в капсулу, то он вместе со всеми своими методами в этой капсуле и живет, что очень удобно. То есть метод len гораздо проще определить, чем функцию len. Также с этой капсулой нужно как-то взаимодействовать, и, собственно, это называется интерфейсом. Публичные методы, ну или публичные поля, классы, как мы делали в структурах. Собственно, с помощью интерфейса объект из своей капсулы может как-то общаться со внешним миром. Следующая вещь — это наследование. Наследование, собственно — это наследование каких-то признаков от своего предка, например, сферической формы. Наследование мы тоже сегодня сделаем. Ну, это очень удобно, когда вам нужно что-то доопределить. Ну например, вы написали текстовый редактор, и у вас есть объект текстовый файл, в который вы умеете много чего делать. И вдруг появился какой-то новый язык, какая-то новая кодировка, и вы хотите сделать что-то, чтобы у вас поддерживалась эта новая кодировка. Вы берете свой класс и просто от него наследуете нового потомка для новой кодировки, и в нем заменяете или добавляете или наоборот выключаете какие-то методы, которые были у родительского класса, а не переписываете все с нуля и не замусориваете свой проект какими-то if-ами, какими-то вставками, что, собственно, здорово облегчает жизнь, если грамотно продумать структуру. И наконец полиморфизм, изменчивость в некотором смысле. Ну, здесь трактовки бывают разные. Одна из них, ну, наиболее логичная — это способ единообразный доступа к объектам разной природы. Опять же наш пример. Функция len умеет читать длину разных объектов. Плюс — операция, ну, она не является функцией, но тем не менее, на самом деле это метод класса, тоже он умеет работать с числами, с вещественными числами, со строками, много с чем. Соответственно, у вас предоставляется более-менее единообразный интерфейс для доступа к разным данным, ну то есть по сути это изменчивость данных при сохранении единообразия интерфейса. Вот такая штука полиморфизм. Классом при этом называется описание структуры, то есть это поля класса, какие данные могут жить внутри него, и это методы, код непосредственно, который может выполняться. Экземпляры класса называются объектами. То есть что такое объект? Вот мы описали какую-то структуру, футбольный мячик, описали методы, которые можно к нему применять, там пнуть мячик, поймать мячик, там еще что-то сделать с мячиком. Это просто описание. А потом мы начинаем делать конкретные мячики, объекты, они могут там отличаться по своим каким-то внутренним данным. Например, если там вес мячика — это какой-то параметр, который может изменяться у разных объектов, то вот мячики получатся разными, хотя будут представителями одного и того же класса. Ну и кроме того, даже разные объекты одного класса могут взаимодействовать между собой. Для этого есть специальные поля, которые называются статические поля. Они доступны абсолютно изо всех объектов класса. Если вы в одном поменяете, то в других тоже изменятся. Конечно, вещь это очень специфичная, нужна редко, но для разных задач, например, вы хотите понять, сколько мячей у вас было создано. Вы можете создать статическую переменную, и каждый раз, когда создается новый мячик, он будет увеличивать ее на единицу. Например, если вы хотите... также если мячик сломался, вы его удалили — можете уменьшать на единицу. И таким образом вы в каждый момент времени будете знать, сколько у вас всего мячиков существует. Ну, в основном это нужно для каких-то отладочных целей, для измерения эффективности, ну или для других каких-то очень специфичных задач, которых мы сегодня касаться не будем. И теперь, когда мы понимаем, для какого рода задач у нас могут применяться методы объектно-ориентированного программирования, понимаем, какими свойствами оно обладает, перейдем к практической реализации классов. Но для этого нам потребуется небольшое погружение в математическую теорию, и сейчас я расскажу вам очень-очень примитивно, как устроены комплексные числа. [МУЗЫКА] [МУЗЫКА]