LINUX.ORG.RU

Инкапсуляция.

 


1

2

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

Собственно, инкапсуляция присутствует неявно и в ФП, например, замыкания - это вариант инкапсуляции. Но ее можно вообще изобразить явно, например:

(define fu (lambda(arg) (if (= arg 'I-am-foo) (bar))))
Тут очевидно, что мы скрываем вызов bar, от всех функций которые не отправляют нужное сообщение. Ключевое слово: ОТ ФУНКЦИЙ. Можно, в других случаях, говорить, что от объектов. Короче, от программных сущностей.

Однако, я часто наблюдаю, что под инкапсуляцией понимается сокрытие не от программных сущностей, а от самого программиста. Например:

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

What a fuck?!!! Нахрена прятать внутреннюю реализацию от самого программиста, а не от программных объектов?

Инкапсуляция — это в первую очередь абстрагирование от реализации. Для fu важен не сам факт сокрытия вызова bar при определённых сообщениях, а то, что fu корректно реагирует на получение сообщений (вызывая или не вызывая bar, но об этом уже не следует волноваться).

Нахрена в Си++ придумали private-поля и почему из fu нельзя вытащить её реализацию — это уже другой вопрос.

ilammy ★★★ ()

What a fuck?!!! Нахрена прятать внутреннюю реализацию от самого программиста, а не от программных объектов?

чтобы избавить от ненужных и вредных раздумий.

dikiy ★★☆☆☆ ()
Ответ на: комментарий от ilammy

Инкапсуляция — это в первую очередь абстрагирование от реализации.

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

anonimous ()
Ответ на: комментарий от anonimous

Ну да. Наследование — это умение повторно использовать код, полиморфизм — это умение использовать инкапсуляцию и наследование вместе, а баззворды — это зло.

ilammy ★★★ ()
Ответ на: комментарий от ilammy

Спасибо большое за ответы. Если б не Вы, мне б еще долго пришлось путаться в 3-х соснах.:)

anonimous ()

Даже википедия пишет:


In programming languages, encapsulation is used to refer to one of two related but distinct notions, and sometimes to the combination[1][2] thereof:

A language mechanism for restricting access to some of the object's components.[3][4]
A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data.[5][6]

Some programming language researchers and academics use the first meaning alone or in combination with the second as a distinguishing feature of object oriented programming, while other programming languages which provide lexical closures view encapsulation as a feature of the language orthogonal to object orientation.

The second definition is motivated by the fact that in many OOP languages hiding of components is not automatic or can be overridden; thus, information hiding is defined as a separate notion by those who prefer the second definition.

http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)

invy ★★★★★ ()
Последнее исправление: invy (всего исправлений: 1)

Не бойся, в твоём Питоне инкапсуляции нет, так что он не ООП.

Нахрена прятать внутреннюю реализацию от самого программиста, а не от программных объектов?

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

comp00 ★★★★ ()
Последнее исправление: comp00 (всего исправлений: 1)

Инкапсуляция это отделение интерфейса от реализации, и к сокрытию данных не имеет никакого отношения.

В некотором смысле, идеальный пример инкапсуляции для классического single-dispatch ООП это Microsoft COM.

lovesan ★☆ ()

Нахрена прятать внутреннюю реализацию от самого программиста, а не от программных объектов?

Чтобы было проще продавать клозедсорц блобы с плановыми багами.

PolarFox ★★★★★ ()
Ответ на: комментарий от ilammy

Что за бред. Полиморфизм это способность некоторого куска кода работать с разными данными используя один и тот же интерфейс.

К ООП это понятие вообще не относится никак, и появилось не в нем.

Бывает два вида полиморфизма:

1) ad-hoc - грубо говоря, это когда ты явно указываешь варианты перегрузки функции

2) параметрический полиморфизм - способность кода работать с разными данными совершенно одинаково. Пример - generics в C# и Java.

lovesan ★☆ ()
Ответ на: комментарий от lovesan

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

ilammy ★★★ ()

Нахрена прятать внутреннюю реализацию от самого программиста

очевидно для того, что-бы её можно было ИЗМЕНИТЬ. Не меняя остальной код. Ну например ты юзаешь мою сортировку пузырьком, а я прочитаю Кнута, узнаю, что пузырёк == говно, и поставлю qsort. Когда ты в следующий раз соберёшь свою программу, ты увидишь, что она стала быстрее. Но для этого мне надо скрыть от тебя мою реализацию, что-бы ты не смог её менять. Иначе, своим qsort'ом я поломаю твой код(который думает, что это — пузырёк).

emulek ()
Ответ на: комментарий от anonimous

Если умение абстрагироваться от реализациии - это и есть то, что называют инкапсуляцией

дело не в умении. У тебя всегда будет соблазн как-то оптимизировать свой код, и подточить его под мой. А этого делать нельзя, ибо твоя задрочка неминуемо будет поломана изменениями в моём коде.

А когда ты один пишешь, то инкапсуляция и не слишком-то и нужна.

emulek ()
Ответ на: комментарий от comp00

Как по мне так это странный микроконтроль черное-белое. Когда выходит новая версия с поломанным апи, то все равно приходится все переписывать (или генерить огромные затраты на обратную совместимость). Интереснее было бы так: опуститься уровнем ниже и сказать «ребята, вот паблик полный, вот для знакомых, а вот для совсем прошаренных». Типа public, friends, husband. И если с public и friends все понятно, то husband может ставить реализацию как хочет. А когда поставщик класса меняет интерфейс, он просто бампает нужные секции, чтобы при сборке клиент поймал варнинги (если они вообще вылезут) и поправил что где нужно.

arturpub ★★ ()
Ответ на: комментарий от arturpub

qsort тоже == говно

ты лиспер что-ли? qsort это сортировка на месте, она плохо ложится на ФП.

emulek ()
Ответ на: комментарий от arturpub

Когда выходит новая версия с поломанным апи, то все равно приходится все переписывать

составители кривых API должны страдать. Как и их пользователи.

emulek ()
Ответ на: комментарий от emulek

ты лиспер что-ли?

б-же упоси.

Просто мне mergesort нравится, а у qsort'а души нет.

arturpub ★★ ()
Ответ на: комментарий от emulek

You're so negative. Почему должны? Почему нельзя попробовать сделать так, чтобы было максимально несложно решать основную проблему — кстати какую?

arturpub ★★ ()
Ответ на: комментарий от emulek

она плохо ложится на ФП.

qs [] = []
qs (x:xs) = qs l ++ [x] ++ qs r where (l,r) = partition (< x) xs
yoghurt ★★★★★ ()
Ответ на: комментарий от anonimous

Если умение абстрагироваться от реализациии - это и есть то, что называют инкапсуляцией, я вообще в шоке.:)

вполне адекватная реакция.

ООП, как оно есть в упомянутых плюсах, такой же набор костылей как и сами плюсы.

Смотри лучше джаву, или smalltalk

MyTrooName ★★★★★ ()
Ответ на: комментарий от arturpub

Просто мне mergesort нравится, а у qsort'а души нет.

у qsort'f код красивый, только его нужно понимать.

emulek ()
Ответ на: комментарий от arturpub

You're so negative. Почему должны? Почему нельзя попробовать сделать так, чтобы было максимально несложно решать основную проблему — кстати какую?

ну вот что-бы «максимально несложно», как раз и нужен хорошо продуманный API, в котором функции не меняются, и потом он и не ломается. Пример такого API — WinAPI(который в WinNT). Спроектированный в начале девяностых, он умудрился продержаться более 10и лет, а это огромный срок для отрасли.

emulek ()
Ответ на: комментарий от yoghurt

qs (x:xs) = qs l ++ [x] ++ qs r where (l,r) = partition (< x) xs

это говно только внешне похоже на qsort. Попробуй своим говнокодом отсортировать сколько-нибудь большой массив, и сравни время с qsort(3) из glibc.

emulek ()
Ответ на: комментарий от comp00

4.2. В питоне инкапсуляция такая же как в плюсах. А скрыть данные своего процесса от этого же процесса невозможно, private и protected не более чем рекомендации программисту не лазить куда то грязными оуками.

AIv ★★★★★ ()

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

AIv ★★★★★ ()
Ответ на: комментарий от emulek
*Main> :m + System.Random
*Main System.Random> g <- getStdGen
*Main System.Random> let rr = take 8192 $ randoms g :: [Integer]
*Main System.Random> :set +s
*Main System.Random> last $ qs rr
9223020890336782088
(0.05 secs, 54244792 bytes)
*Main System.Random> 
yoghurt ★★★★★ ()
Ответ на: комментарий от AIv

Ну давай, напиши мне код на С++, менящий состаяние private члена инстанса вне класса. Или заменяющий описание метода класса. В питоне это делается легко.

не более чем рекомендации

Это как раз в питоне инкапсуляция строится на рекомендациях. В c++ все жестко.

comp00 ★★★★ ()
Ответ на: комментарий от comp00

В c++ все жестко.

Особенно в районе reinterpret_cast и undefined behaviour :-)

Begemoth ★★★★★ ()
Ответ на: комментарий от Begemoth

Причем тут это вообще? Мы вро де бы об оопговорили, а не об приведении типов.
// а вообще, используешь reinterpret_cast при живых dynamic_cast и static_cast — ССЗБ

comp00 ★★★★ ()
Ответ на: комментарий от comp00

Ближе к вечеру напишу, сейчас сижу с телефона. Пока что рекомендую подумать что будет если при сборке указать флаг -Dprivate=public

AIv ★★★★★ ()
Ответ на: комментарий от AIv

что будет если при сборке указать флаг -Dprivate=public

И какой же профит от этого выстрела в ногу из ракетницы?

comp00 ★★★★ ()
Ответ на: комментарий от comp00

Ты спрашивал как обойти контроль доступа к членам класса, -Dprivate=public, как и reinterpret_cast к типу с идентичной структурой, но иными квалификаторами доступа, дадут тебе это сделать. А доступ к деталям реализации - это выстрел в ногу в не зависимости от степени контроля языка.

Begemoth ★★★★★ ()
Ответ на: комментарий от yoghurt

Я не особо удивлюсь, если в реализациях этого вашего Хаскеля специально вкостылена оптимизация того qsort для списков, за кулисами переписывающая qsort в mergesort.

ilammy ★★★ ()
Ответ на: комментарий от emulek

у qsort'f код красивый, только его нужно понимать.

У mergesort он тоже красивый. Mergesort — это тот же qsort, только с другого конца.

ilammy ★★★ ()

Нахрена прятать внутреннюю реализацию от самого программиста, а не от программных объектов?

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

WhiteClick ()
Ответ на: комментарий от comp00

Ну давай, напиши мне код на С++, менящий состаяние private члена инстанса вне класса

В питоне это делается легко.

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

В c++ все жестко.

быдлокод можно писать и в C++, я гарантирую это!

emulek ()
Ответ на: комментарий от ilammy

У mergesort он тоже красивый. Mergesort — это тот же qsort, только с другого конца.

ну а я про что?

emulek ()
Ответ на: комментарий от comp00

Ну давай, напиши мне код на С++, менящий состаяние private члена инстанса вне класса.

#include <stdio.h>

class A{
private:
	int x;
public:
	A():x(0){}
	void out_x(){ printf("%i\n", x); }
};

int main(){
	A a;
	a.out_x();
	*(int*)&a = 123;
	a.out_x();
}
aiv@aivbook:~/tmp$ g++ -Wall test.cpp
aiv@aivbook:~/tmp$ ./a.out 
0
123
aiv@aivbook:~/tmp$

Еще раз, НЕВОЗМОЖНО в ЯП поддерживающем ручное управление памятью «скрыть» какие то данные принадлежащие процессу от чего то в этом процессе. Можно только обфусцировать че нить, но это другая история, и главное это ненужно - инкапсуляция не имеет НИКАКОГО отношения к «сокрытию» данных и методов в том виде, в котором Вы это «сокрытие» понимаете.

AIv ★★★★★ ()
Ответ на: комментарий от Begemoth

А доступ к деталям реализации - это выстрел в ногу в не зависимости от степени контроля языка.

Наверное только не доступ, а попытка программиста работать напрямую с деталями реализации минуя предлагаемый интерфейс. А то сейчас тут некоторые поймут «доступ» как возможности ЯП и опять гуляй деревня... ;-)

AIv ★★★★★ ()
Ответ на: комментарий от AIv

Ух ты, красиво, а если еще и арифметику указателей использовать, то вообще по полям ходить можно.

comp00 ★★★★ ()
Ответ на: комментарий от comp00

Таки да. Только надо помнить, что у виртуального класса вначале сидит пойнтер на таблицу вирт. функций.

AIv ★★★★★ ()
Ответ на: комментарий от comp00

Ну давай, напиши мне код на С++, менящий состаяние private члена инстанса вне класса.

Мусье не умеет записывать значения по смещению от базы?

anonymous ()
Ответ на: комментарий от AIv

*(int*)&a = 123;

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

Еще раз, НЕВОЗМОЖНО в ЯП поддерживающем ручное управление памятью «скрыть» какие то данные принадлежащие процессу от чего то в этом процессе.

ну потому что значение указателя вообще говоря глобально. Т.е. если есть пара массивов, то можно сделать указатель на один массив, а потом перевести его на другой(тупо инкрементном). И это говно даже будет работать(хоть и UB).

инкапсуляция не имеет НИКАКОГО отношения к «сокрытию» данных и методов в том виде, в котором Вы это «сокрытие» понимаете.

ИМХО private следует понимать как НЕ НУЖНО ТУДА ЛЕЗТЬ. Не потому что это «нельзя» и «запрещено», а потому, что это в любой момент могут переделать.

emulek ()
Ответ на: комментарий от comp00

то вообще по полям ходить можно.

по минным полям тоже «можно» ходить. И нужно, если ты настолько тупой, что не осилил прочитать табличку.

emulek ()
Ответ на: комментарий от AIv

что у виртуального класса вначале сидит пойнтер на таблицу вирт. функций.

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

И да, никто никогда и нигде не гарантировал, что именно в начале.

И да, порядок полей тоже вовсе не обязан быть тем, как описано в классе. ЕМНИП там тоже есть тонкости.

Короче — добро пожаловать в клуб самоубийц.

emulek ()
Ответ на: комментарий от emulek

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

comp00 ★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.