История изменений
Исправление 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 не нашел(может плохо искал) обьявлений приватности
контролируется через пакеты и если говорить о полях класса - через объявленные методы чтения/записи
протектности, финальности
Делается через метаобъектный протокол, но на самом деле, в большинстве случаев просто ненужно.