Тема: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

Яка різниця між об*єктно орієнтованим та узагальненим програмуванням?

2

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

УП, це множина, котрій належить ООП ?  *SCRATCH*

Говоріть українською! Живіть українською! Відчувайте українською!

3

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

Якщо я правильно розумію, УП — це макроси, дженеріки, темплейти (загалом, такі описові конструкції, де тип виступає як параметр), тоді як ООП — це ієрархія класів, інкапсуляція даних та методів, і т.д. В деяких місцях ці підходи перетинаються та взаємодіють, хоча можливе як ООП без УП, так і УП без ООП.

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊

4

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

Основне - це в ООП є пізнє зв'язування/поліморфізм. Дженерики лише створюють кілька варіантів функцій/типів, які зв'язуються до запуску програми.
Інкапсуляція - це більше до модульного програмування. Наслідування - навіть не знаю, але ООП без нього може жити, а без поліморфізму - ні.

Подякували: Yola1

5

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

koala написав:

Інкапсуляція - це більше до модульного програмування.

Чому ж, модуль може бути взагалі без глобальних/статичних змінних, з самими функціями без побічного ефекту (і такий підхід у чомусь навіть більш правильний). А от ООПшний поліморфізм без інкапсуляції навіть не уявляю, як красиво зробити.

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊

6

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

P.Y. написав:
koala написав:

Інкапсуляція - це більше до модульного програмування.

Чому ж, модуль може бути взагалі без глобальних/статичних змінних, з самими функціями без побічного ефекту (і такий підхід у чомусь навіть більш правильний).

Так клас теж може бути без статики і методів з побічними ефектами, правилами не заборонено.

P.Y. написав:

А от ООПшний поліморфізм без інкапсуляції навіть не уявляю, як красиво зробити.

Ми всі тут дорослі люди (c) ван Россум.

Взагалі, інкапсуляція включає дві окремі фічі: сутність, що включає дані і методи (модуль чи об'єкт - однаково підходять), та контроль доступу програміста до цих даних і методів, і тут якраз модулі виграють, бо їх для того і придумали, щоб приховувати деталі реалізації. А от Python чи JavaScript безумовно ООПшні, але без приховування елементів.

7

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

Я про те, що дві різні структури даних (без методів, лише з можливістю ідентифікувати тип) поліморфічно як обробиш? Це треба робити щоразу галуження, де якщо тип такий, то візьми такі поля й оброби їх так, якщо тип другий — то якісь другі, і т.д. І все, що з таким недополіморфізмом працює, вимагатиме переробки коду, якщо ми введемо ще один такий тип. Безумовно, так писати код можливо, але де тут краса та гнучкість ООП?

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊

8

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

Так клас теж може бути без статики і методів з побічними ефектами, правилами не заборонено

Якщо під статикою розуміємо те, що static у Java'і, то це більше скидається на інтеграцію модульного функціоналу в класи (і клас, де все static, має більше спільного з модулем, аніж з класом).
А от аналогів нестатичних полів (тобто, тих, що належать екземплярові класу) в модульному підході не передбачено. І навіть маючи такі поля, можна зробити їх недоступними для змін після ініціалізації конструктором, а методи — з доступом до читання полів, але без побічного ефекту в вигляді запису. Таким чином, отримаємо immutable-об'єкти.

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊
Подякували: leofun011

9

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

P.Y. написав:

Я про те, що дві різні структури даних (без методів, лише з можливістю ідентифікувати тип) поліморфічно як обробиш? Це треба робити щоразу галуження, де якщо тип такий, то візьми такі поля й оброби їх так, якщо тип другий — то якісь другі, і т.д. І все, що з таким недополіморфізмом працює, вимагатиме переробки коду, якщо ми введемо ще один такий тип. Безумовно, так писати код можливо, але де тут краса та гнучкість ООП?

Ну, насправді поліморфний виклик - це лише (напівпсевдокодом)

object->vtable[METHOD_NAME](object, parameters);

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

VTABLE[typeof(object)][METHOD_NAME](object, parameters);

і ніякого галуження не треба. Додаємо ще один тип - додаємо ще одну таблицю віртуальних функцій.
Так, треба писати зайвий раз vtable[] та object, але в іншому краса та гнучкість зберігаються. Тим більше, що це можна обгорнути в макрос і буде

VCALL(METHOD_NAME, object, parameters);
P.Y. написав:

А от аналогів нестатичних полів (тобто, тих, що належать екземплярові класу) в модульному підході не передбачено. І навіть маючи такі поля, можна зробити їх недоступними для змін після ініціалізації конструктором, а методи — з доступом до читання полів, але без побічного ефекту в вигляді запису. Таким чином, отримаємо immutable-об'єкти.

Раджу глянути, як зроблені модулі та доступ до їхніх елементів у Rust.

10

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

До речі, якщо мова зайшла про Rust, то він якраз може добре підказати, в чому різниця між узагальненим програмуванням та ООП, бо компілятор намагається замінити поліморфізм на узагальнене програмування де тільки можна. Отже, нехай у нас є такий код:
https://play.rust-lang.org/?gist=bf5b80 … ition=2015

Прихований текст

trait Figure: std::fmt::Debug {
    fn area(&self) -> f64;
}

#[derive(Debug)]
struct Square { side:f64 }

impl Figure for Square {
    fn area(&self) -> f64 { self.side.powi(2) }
}

#[derive(Debug)]
struct Rectangle { height:f64, width:f64 }

impl Figure for Rectangle {
    fn area(&self) -> f64 { self.height * self.width }
}

#[derive(Debug)]
struct Circle { radius:f64 }

impl Figure for Circle {
    fn area(&self) -> f64 { std::f64::consts::PI * self.radius.powi(2) }
}

fn print_figure<T>(f:&T) where T:Figure+?Sized {
    println!("Figure {:?} area = {}", f, f.area() );
}

fn main() {
    let s = Square{ side: 3.0 };
    let r = Rectangle{ width: 2.0, height: 6.0 };
    let c = Circle{ radius: 2.0 };
    println!("Generic calls:");
    print_figure(&s);
    print_figure(&r);
    print_figure(&c);
    println!("Polymorphic calls:");
    let v:Vec<&Figure> = vec![&s,&r,&c];
    for f in v {
        print_figure(f);
    }
}

Компілятор сформує 4 різні реалізації print_figure: для типів Square, Rectangle, Circle та для trait object-а Figure. Trait object складається з двох посилань: на реальну структуру та на таблицю віртуальних функцій (у цьому випадку - area та fmt з Debug). Відповідно, перші три виклики area та fmt будуть неполіморфні; а от у циклі буде викликано саме поліморфну версію.

Подякували: leofun01, LoganRoss, P.Y.3

11

Re: Різниця між об*єктно орієнтованим та узагальненим програмуванням?

koala написав:
P.Y. написав:

Я про те, що дві різні структури даних (без методів, лише з можливістю ідентифікувати тип) поліморфічно як обробиш? Це треба робити щоразу галуження, де якщо тип такий, то візьми такі поля й оброби їх так, якщо тип другий — то якісь другі, і т.д. І все, що з таким недополіморфізмом працює, вимагатиме переробки коду, якщо ми введемо ще один такий тип. Безумовно, так писати код можливо, але де тут краса та гнучкість ООП?

Ну, насправді поліморфний виклик - це лише (напівпсевдокодом)

object->vtable[METHOD_NAME](object, parameters);

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

VTABLE[typeof(object)][METHOD_NAME](object, parameters);

і ніякого галуження не треба. Додаємо ще один тип - додаємо ще одну таблицю віртуальних функцій.
Так, треба писати зайвий раз vtable[] та object, але в іншому краса та гнучкість зберігаються. Тим більше, що це можна обгорнути в макрос і буде

VCALL(METHOD_NAME, object, parameters);

По суті, це низькорівнева реалізація ООП, де все одно є методи класів, хай навіть синтаксично оформлені дещо інакше, ніж у мовах назразок Java чи C++.

py -3 -m pip install git+https://github.com/snoack/python-goto
∩⍴○⌈⍴⍺/∧\∨/⊢○ ⌿⍀⍴⌊
Подякували: leofun011