LINUX.ORG.RU

История изменений

Исправление lovesan, (текущая версия) :

я просто посмотрел CLOS, и загрустил, вспоминая старые добрые С++ классы. CLOS оказался классиечкой подделкой под ООП, постоянно втекаемой во многие недоязычки, где ради «гибкости» определения методов вынесены за декларацию класса, отчего класс разваливается и никаких утверждений сделать о классе нельзя.

Я тебе щас взорву мозг.

В C++ (как и практически во всех языках с симуловском ООП), методы на самом деле ТОЖЕ «вынесены» за классы. И на самом деле являются просто функциями, которые первым аргументом принимают объект класса. Особенно это наглядно видно в Python, но давай рассмотрим C++.

Например, если мы скомпилируем(g++ -c hello.cxx) такой файл:

#include <string>

class Foo
{
public:
    void Hello(const char* who);
};

int main(void)
{
    Foo foo;
    foo.Hello("World");
    return 0;
}

И натравим на полученный объектник nm, то мы найдем там символ _ZN3Foo5HelloEPKc

Что это такое? Это символ, который указывает на функцию Foo::Hello(char const*), которая должна быть определена в другом объектнике. (вот тут можно убедиться в этом: http://demangler.com/)

Это просто внешняя функция от двух аргументов. Типы аргументов: Foo* и std::string

Чтобы в этом убедиться, таки определим эту функцию во внешнем модуле, но уже на сишечке(gcc -c impl.c):

#include <stdio.h>

void _ZN3Foo5HelloEPKc(void* this, const char* who)
{
    printf("Hello, %s!\n", who);
}

Теперь слинкуем и проверим:

lovesan@ubuntu:~$ g++ -o hello hello.o impl.o
lovesan@ubuntu:~$ ./hello
Hello, World!

Исключением, отчасти, является, например, дотнет. Но методы там точно так же это просто функции, которые принимают первым аргументом this. Просто они сгруппированы в классы.

То есть всё твое ООП это, получается, синтаксический сахар…

…Который на лиспе делается макросами, так как симуловское ООП это подмножество CLOS.

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

Давай попробуем с ее помощью определить аналогичный вышеописанному класс:

(define-dotnet-callable-class foo ()
  (:defmethod hello :void ((who :string))
    (format t "Hello, ~a" who)))

Ну, создадим экземпляр объекта, и попытаемся его вызывать:

CL-USER> (defvar *foo* (make-instance 'foo))
*FOO*
CL-USER> (hello *foo* "World")
Hello, World

А теперь, внимание, финт ушами:

(named-readtables:in-readtable bike-syntax)

И вызываем его как в «обычном» ООП (синтаксис становится идентичен Objective-C):

CL-USER> [*foo* Hello "World!"]
Hello, World!

Что же такое hello? Да это просто та же самая функция от двух аргументов.

CL-USER> (describe (function hello))
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::HELLO (1)>
  [generic-function]

Lambda-list: (THIS WHO)
Argument precedence order: (THIS WHO)
Derived type: (FUNCTION (T T) *)
Method-combination: STANDARD
Methods:
  (HELLO (FOO T))

Slots with :INSTANCE allocation:
  SOURCE                         = NIL
  PLIST                          = NIL
  %DOCUMENTATION                 = NIL
  INITIAL-METHODS                = NIL
  ENCAPSULATIONS                 = NIL
  NAME                           = HELLO
  METHODS                        = (#<STANDARD-METHOD COMMON-LISP-USER::HELLO (FOO T) {100866BE33}>)
  METHOD-CLASS                   = #<STANDARD-CLASS COMMON-LISP:STANDARD-METHOD>
  %METHOD-COMBINATION            = #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD () {100025CDB3}>
  DECLARATIONS                   = NIL
  ARG-INFO                       = #S(SB-PCL::ARG-INFO..
  DFUN-STATE                     = (#<FUNCTION (LAMBDA (SB-PCL::.ARG0. SB-PCL::.ARG1.)..
  %LOCK                          = #<SB-THREAD:MUTEX "GF lock" free owner=0>

Да, кстати обобщенные функции CLOS, как видно это тоже такие объекты CLOS. В Common Lisp вообще у всего есть класс, и всё является объектом, даже небо и даже Аллах.

также я в CLOS не нашел(может плохо искал) обьявлений приватности

контролируется через пакеты и если говорить о полях класса - через объявленные методы чтения/записи

протектности, финальности

Делается через метаобъектный протокол, но на самом деле, в большинстве случаев просто ненужно.

Исходная версия lovesan, :

я просто посмотрел CLOS, и загрустил, вспоминая старые добрые С++ классы. CLOS оказался классиечкой подделкой под ООП, постоянно втекаемой во многие недоязычки, где ради «гибкости» определения методов вынесены за декларацию класса, отчего класс разваливается и никаких утверждений сделать о классе нельзя.

Я тебе щас взорву мозг.

В C++ (как и практически во всех языках с симуловском ООП), методы на самом деле ТОЖЕ «вынесены» за классы. И на самом деле являются просто функциями, которые первым аргументом принимают объект класса. Особенно это наглядно видно в Python, но давай рассмотрим C++.

Например, если мы скомпилируем(g++ -c hello.cxx) такой файл:

#include <string>

class Foo
{
public:
    void Hello(const char* who);
};

int main(void)
{
    Foo foo;
    foo.Hello("World");
    return 0;
}

И натравим на полученный объектник nm, то мы найдем там символ _ZN3Foo5HelloEPKc

Что это такое? Это символ, который указывает на функцию Foo::Hello(char const*), которая должна быть определена в другом объектнике. (вот тут можно убедиться в этом: http://demangler.com/)

Это просто внешняя функция от двух аргументов. Типы аргументов: Foo* и std::string

Чтобы в этом убедиться, таки определим эту функцию во внешнем модуле, но уже на сишечке(gcc -o impl.o impl.c):

#include <stdio.h>

void _ZN3Foo5HelloEPKc(void* this, const char* who)
{
    printf("Hello, %s!\n", who);
}

Теперь слинкуем и проверим:

lovesan@ubuntu:~$ g++ -o hello hello.o impl.o
lovesan@ubuntu:~$ ./hello
Hello, World!

Исключением, отчасти, является, например, дотнет. Но методы там точно так же это просто функции, которые принимают первым аргументом this. Просто они сгруппированы в классы.

То есть всё твое ООП это, получается, синтаксический сахар…

…Который на лиспе делается макросами, так как симуловское ООП это подмножество CLOS.

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

Давай попробуем с ее помощью определить аналогичный вышеописанному класс:

(define-dotnet-callable-class foo ()
  (:defmethod hello :void ((who :string))
    (format t "Hello, ~a" who)))

Ну, создадим экземпляр объекта, и попытаемся его вызывать:

CL-USER> (defvar *foo* (make-instance 'foo))
*FOO*
CL-USER> (hello *foo* "World")
Hello, World

А теперь, внимание, финт ушами:

(named-readtables:in-readtable bike-syntax)

И вызываем его как в «обычном» ООП (синтаксис становится идентичен Objective-C):

CL-USER> [*foo* Hello "World!"]
Hello, World!

Что же такое hello? Да это просто та же самая функция от двух аргументов.

CL-USER> (describe (function hello))
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::HELLO (1)>
  [generic-function]

Lambda-list: (THIS WHO)
Argument precedence order: (THIS WHO)
Derived type: (FUNCTION (T T) *)
Method-combination: STANDARD
Methods:
  (HELLO (FOO T))

Slots with :INSTANCE allocation:
  SOURCE                         = NIL
  PLIST                          = NIL
  %DOCUMENTATION                 = NIL
  INITIAL-METHODS                = NIL
  ENCAPSULATIONS                 = NIL
  NAME                           = HELLO
  METHODS                        = (#<STANDARD-METHOD COMMON-LISP-USER::HELLO (FOO T) {100866BE33}>)
  METHOD-CLASS                   = #<STANDARD-CLASS COMMON-LISP:STANDARD-METHOD>
  %METHOD-COMBINATION            = #<SB-PCL::STANDARD-METHOD-COMBINATION STANDARD () {100025CDB3}>
  DECLARATIONS                   = NIL
  ARG-INFO                       = #S(SB-PCL::ARG-INFO..
  DFUN-STATE                     = (#<FUNCTION (LAMBDA (SB-PCL::.ARG0. SB-PCL::.ARG1.)..
  %LOCK                          = #<SB-THREAD:MUTEX "GF lock" free owner=0>

Да, кстати обобщенные функции CLOS, как видно это тоже такие объекты CLOS. В Common Lisp вообще у всего есть класс, и всё является объектом, даже небо и даже Аллах.

также я в CLOS не нашел(может плохо искал) обьявлений приватности

контролируется через пакеты и если говорить о полях класса - через объявленные методы чтения/записи

протектности, финальности

Делается через метаобъектный протокол, но на самом деле, в большинстве случаев просто ненужно.