Объектно-ориентированная модель языка Python



Я придумал термин «объектно-ориентированный», и вот что я вам скажу, я не имел ввиду С++.

Алан Кей ''OOPSLA '97''

Дизайн Smalltalk — и его существование вообще — обусловлен тем, что все, что мы можем описать, возможно представить рекурсивной композицией отдельных видов поведенческих строительных блоков, которые внутри самих себя скрывают свою текущую комбинацию состояния и процессов, и могут взаимодействовать друг с другом только посредством обмена сообщениями.

Алан Кей ''The History Of Smalltalk''

 

1972 г.: Деннис Ричи из Bell Lab’s разработал язык программирования «С» (Си). Алан Кей из компании Xerox разработал объектно-ориентированный язык программирования Smalltalk.

Smalltalk?!

Выдержки из статьи, расположенной по адресу

http://www.smalltalk.ru/articles/smalltalk.html

Все началось в 1971-ом году, когда в исследовательскую лабораторию Xerox Palo Alto (Xerox PARC) пришел Alan Kay. Именно это человек впервые употребил термин object-oriented

Параллельно с этим он работал над созданием языка программирования, целиком базирующегося на принципах объектно-ориентированного программирования. Он провел аналогию с живым организмом, состоящим из клеток, которые обмениваются между собой информацией только посредством посылки сообщений.

Его целью было создание системы с рекурсивным дизайном, в которой даже самая малая ее часть повторяет возможности системы в целом. И которая развивается посредством последовательного изменения своего состояния. Это коренным образом отличалось от традиционного подхода при конструировании программных систем.

Традиционная система представляет множество данных различных типов, и имеет различные способы работы с ними - числа целые и вещественные, строки, массивы, множества, функции, объекты, процессы, внешние носители и т.д. Такое разнообразие вносит излишнюю сложность, затрудняет изучение и препятствует хорошей масштабируемости.

В языке Smalltalk, основной конструкцией является конструкция посылки сообщения. Язык является динамически типизированным, это означает, что в объявлениях не содержится указание типов. Все данные являются частными, а все методы публичными. Простейшие типы данных: число, строка, множество - являются полноправными объектами, для которых можно определять методы точно так же, как и для любых других объектов.

Но Smalltalk - это не просто язык, это динамическая среда исполнения, в которой объекты постоянно создаются, развиваются и уничтожаются. Среда разработки Smalltalk является лучшей иллюстрацией возможностей системы, она целиком написана на самом языке и любая ее часть может быть динамически модифицирована средствами этой же среды…

Объектно-ориентированное программирование

Еще задолго до появления Smalltalk Алан Кей сформулировал три фундаментальных принципа объектно-ориентированного программирования:

· Объект – базовая единица объектно-ориентированной системы.

· Объекты могут обладать состоянием.

· Посылка сообщения – единственный способ обмена информацией между объектами.

Таким образом, видно, что изначальное определение существенно отличается от привычного нам инкапсуляция-полиморфизм-наследование, которое уже имело место до появления Smalltalk в языке Simula-67.

Но, к сожалению, исторически сложилось так, что именно Simula послужила образцом для появления многих известных объектно-ориентированных языков.

Попробуем рассмотреть, в каком отношении находятся эти два определения.

· Инкапсуляция. Естественным образом следует из первоначального определения, так как объекты заключают в себе свои данные и могут взаимодействовать только посредством посылки сообщения без возможности прямого доступа к внутренней структуре.

· Полиморфизм. Входит в понятие посылки сообщения. Любое сообщение может быть послано произвольному объекту, который сам решает обрабатывать ли его, и если обрабатывать, то каким образом.

· Наследование. Это понятие никоим образом не вводится в определении Алана Кея, так как, по сути, это всего лишь удобный механизм для повторного использования кода, что является, скорее, деталью реализации, а не базовым принципом. Если требовать наличия наследования, тогда под определение объектно-ориентированного языка не будут подпадать языки, основанные на прототипах (prototype-based languages), в которых повторное использование реализовано посредством операции делегирования.

Таким образом, видно, что первоначальное определение, данное Аланом Кеем, является более общим. Кроме того, как отмечает сам автор, операция посылки сообщения является нечто большим, чем операция вызова метода в традиционных языках. Это, пожалуй, самая мощная концепция объектно-ориентированного программирования, отказ от которой сильно снижает эффективность всей идеи.

Чем же таким особым обладает операция посылки сообщения (message passing), по сравнению с обычным вызовом метода (method invocation), который применяется в статически-типизированных языках?

Для начала, стоит разобрать из каких этапов состоят эти две операции.

И то, и другое имеет два основных этапа: поиск метода (method lookup) и собственно вызов метода (method invocation).

В статической системе первый этап выполняется компилятором при трансляции исходного кода в машинное представление. Тут снова появляется две альтернативы - раннее связывание (early binding) и позднее связывание (late binding). В первом случае компилятор заранее знает метод, который получит управление после операции вызова. Во втором случае для каждого класса (интерфейса) компилятор строит свою таблицу методов и использует индекс для извлечения результирующего метода на этапе выполнения.

Первый механизм также называется статической диспетчеризацией (static dispatch), второй - статической диспетчеризацией на основе таблицы виртуальных методов (static vtable-based dispatch).

Операция посылки сообщения в динамической системе оба этапа осуществляет на стадии выполнения программы. Поиск метода (method lookup) выполняется каждый раз перед вызовом метода (method invocation). При этом, если результирующий метод не найден, выполняется поиск метода doesNotUnderstand, который является стандартным обработчиком события "метод не найден". В среде разработки это вызовет окно отладчика, в работающей системе можно либо прервать текущий процесс/нить или продолжить выполнение с занесением сообщения в лог-файл.

Описанный механизм называется динамической диспетчеризацией (dynamic dispatch).

Таким образом, операция посылки сообщения не гарантирует, что она будет обработана каким-то определенным образом или вообще будет обработана. Такое ослабление дает дополнительный уровень абстракции и возможности для повторного использования кода…

ООП в Python

Согласно Алану Кэю — автору языка программирования Smalltalk — объектно-ориентированным может называться язык, построенный с учетом следующих принципов:

· Все данные представляются объектами

· Программа является набором взаимодействующих объектов, посылающих друг другу сообщения

· Каждый объект имеет собственную часть памяти и может иметь в составе другие объекты

· Каждый объект имеет тип

· Объекты одного типа могут принимать одни и те же сообщения (и выполнять одни и те же действия)

Дизайн языка Python построен вокруг объектно-ориентированной модели программирования. Реализация ООП в Python является элегантной, мощной и хорошо продуманной, но вместе с тем достаточно специфической по сравнению с другими объектно-ориентированными языками.

Возможности и особенности:

1. Классы являются одновременно объектами со всеми ниже приведёнными возможностями.

2. Наследование, в том числе множественное.

3. Полиморфизм (все функции виртуальные).

4. Инкапсуляция (два уровня — общедоступные и скрытые методы и поля). Особенность — скрытые члены доступны для использования и помечены как скрытые лишь особыми именами.

5. Специальные методы, управляющие жизненным циклом объекта: конструкторы, деструкторы, распределители памяти.

6. Перегрузка операторов (всех, кроме is, '.', '=' и символьных логических).

7. Свойства (имитация поля с помощью функций).

8. Управление доступом к полям (эмуляция полей и методов, частичный доступ, и т. п.).

9. Методы для управления наиболее распространёнными операциями (истинностное значение, len(), глубокое копирование, сериализация, итерация по объекту, …)

10. Метапрограммирование (управление созданием классов, триггеры на создание классов, и др.)

11. Полная интроспекция.

12. Классовые и статические методы, классовые поля.

13. Классы, вложенные в функции и классы.

 

Объект

Прежде чем мы углубимся в преимущества объектно-ориентированной разработки, рассмотрим более существенный вопрос: что именно такое объект? Это одновременно и сложный, и простой вопрос. Сложный он потому, что изучение любого метода разработки программного обеспечения не является тривиальным. А простой он в силу того, что люди уже мыслят объектно.

Например, когда вы смотрите на какого-то человека, вы видите его как объект. При этом объект определяется двумя компонентами: атрибутами и поведением. У человека имеются такие атрибуты, как цвет глаз, возраст, вес и т. д. Человек также обладает поведением, то есть он ходит, говорит, дышит и т. д. В соответствии со своим базовым определением объект — это сущность, одновременно содержащая данные и поведения.

Слово «одновременно» в данном случае определяет ключевую разницу между объектно-ориентированным программированием и другими методологиями программирования. Например, при процедурном программировании код размещается в полностью отдельных функциях или процедурах. В идеале эти процедуры затем превращаются в «черные ящики», куда поступают входные данные и откуда потом выводятся выходные данные. Данные размещаются в отдельных структурах, а манипуляции с ними осуществляются с помощью этих функций или процедур.

Природа объектов

Объект - нечто, чем можно оперировать. Объект имеет состояние, поведение и идентичность. Структура и поведение сходных объектов определены в общем для них классе. Термины "экземпляр" и "объект" взаимозаменяемы.

Класс - множество объектов с общей структурой и поведением.

Всем вам известны такие понятия как тип и переменная. Исходя из этого, можно сказать, что класс — это то же самое, что и тип, а объект – то же самое что и переменная. Вы привыкли, что тип int означает целое число, float – число с плавающей запятой и т.д. Теперь попытаемся несколько расширить этот набор. Представим, что существует такой тип как человек. Переменной в этом случае будет конкретный человек, например, я, или любой из Вас. Точно так же мы можем ввести класс стол, объектами которого будут, этот стол и тот стол.

Теперь более подробно разберемся с определением объекта. А именно с понятиями состояния, поведения и идентичности.

Состояние

Состояние объекта характеризуется перечнем (обычно статическим) всех свойств данного объекта и текущими (обычно динамическими) значениями каждого из этих свойств. В качестве примера можно рассмотреть автомат, торгующий кофе. Одно из свойств – количество монет, хранящихся в нем. Тот факт, что это свойство всегда есть, определяет статику. Значение этого свойства определяет динамику.

Поведение

Поведение - это то, как объект действует и реагирует; поведение выражается в терминах состояния объекта и передачи сообщений. Иными словами, поведение объекта - это его наблюдаемая и проверяемая извне деятельность.

Операцией называется определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию.

C одной стороны, поведение объекта изменяет его состояние. С другой – поведение зависит от состояния. Действительно, рассмотрим поведение автомата. С одной стороны, одна из частей его поведения – принять монету. Эта часть поведения влияет на часть состояния–количество монет. С другой – именно часть состояния - количество монет определяет в некоторой степени поведение автомата. А именно, наливать ли кофе в стакан или нет. Таким образом можно прийти к выводу, что состояние объекта представляет суммарный результат его поведения.

Поведение объекта строится из его операций. Существует три вида операций

· Модификатор – операция, которая изменяет состояние объекта

· Селектор – операция, считывающая состояние объекта, но не меняющая состояния

· Итератор – операция, позволяющая организовать доступ ко всем частям объекта в строго определенной последовательности

Идентичность

Идентичность - это такое свойство объекта или такой набор свойств, который отличает его от всех других объектов. Например, когда мы программируем, мы можем однозначно определять объект по его имени. Объект, хранящийся в базе данных, мы можем определять по набору свойств, определяющих первичный ключ.

 

Что такое объект

Объекты — это строительные блоки объектно-ориентированных программ. Та или иная программа, которая задействует объектно-ориентированную технологию, по сути является набором объектов. В качестве наглядного примера рассмотрим корпоративную систему, содержащую объекты, которые представляют собой работников соответствующей компании. Каждый из этих объектов состоит из данных и поведений, описанных в последующих разделах.

Данные объектов

Данные, содержащиеся в объекте, представляют его состояние. В терминологии объектно-ориентированного программирования эти данные называются атрибутами. В нашем примере атрибутами работника могут быть номер социального страхования, дата рождения, пол, номер телефона и т. д. Атрибуты включают информацию, которая разнится от одного объекта к другому (ими в данном случае являются работники).

Поведения объектов

Поведение объекта представляет то, что он может сделать. В процедурных языках поведение определяется процедурами, функциями и подпрограммами. В терминологии объектно-ориентированного программирования поведения объектов содержатся в методах, а вызов метода осуществляется путем отправки ему сообщения. Примите по внимание, что в нашем примере с работниками одно из необходимых поведений объекта Employee заключается в задании и возврате значений различных атрибутов. Таким образом, у каждого атрибута будут иметься соответствующие методы, например, setGender() и getGender(). В данном случае, когда другому объекту потребуется такая информация, он сможет отправить сообщение объекту Employee и узнать значение его атрибута gender.

Геттеры и сеттеры

Концепция геттеров и сеттеров поддерживает концепцию скрытия данных. Поскольку другие объекты не должны напрямую манипулировать данными, содержащимися в одном из объектов, геттеры и сеттеры обеспечивают управляемый доступ к данным объекта. Геттеры и сеттеры иногда называют методами доступа и методами-модификаторами соответственно.

Класс. Создание класса

Класс – это абстрактное понятие, сравнимое с понятием категория в его обычном смысле. Допустим, мы имеем какой-то объект реального мира. По определенным свойствам этого объекта (например, у него 4 ножки, сверху ровная поверхность, на нем сидят), можно установить, что он принадлежит к какой-то категории (табурет). Сама категория определяется общими свойствами, которые имеют все экземпляры этой категории.

В программировании класс – это описание структуры объекта и методов работы с ним. С его помощью описывается некоторая сущность реального или выдуманного мира (ее характеристики и возможные действия). Например, класс может описывать студента, автомобиль и т.д. Описав класс, мы можем создать его экземпляр – объект. Объект – это уже конкретный представитель класса.

Класс в языке Python создается.

Для ясности последующего изложения рассмотрим определение класса с точки зрения синтаксиса. Для определения класса используется оператор class:

class имя_класса(надкласс1, надкласс2, ...):

# определения атрибутов и методов класса

У класса могут быть базовые (родительские) классы (надклассы), которые (если они есть) указываются в скобках после имени определяемого класса.

Минимально возможное определение класса выглядит так:

 class A:

pass

В терминологии Python члены класса называются атрибутами, функции класса — методами, а поля класса — свойствами (или просто атрибутами).

Определения методов аналогичны определениям функций, но (за некоторыми исключениями, о которых ниже) методы всегда имеют первый аргумент, называемый по широко принятому соглашению self:

class A:

def m1(self, x):

   # блок кода метода

Определения атрибутов — обычные операторы присваивания, которые связывают некоторые значения с именами атрибутов.

class A:

attr1 = 2 * 2

В языке Python класс не является чем-то статическим после определения, поэтому добавить атрибуты можно и после:

class A:

   pass

 

def myMethod(self, x):

   return x * x

A.m1 = myMethod

A.attr1 = 2 * 2

 


Дата добавления: 2020-01-07; просмотров: 211; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!