OSDev

для всех
Текущее время: 16 апр 2024, 18:10

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 13 ]  На страницу Пред.  1, 2
Автор Сообщение
СообщениеДобавлено: 25 апр 2015, 16:37 
Аватара пользователя

Зарегистрирован: 28 май 2012, 23:44
Сообщения: 237
Откуда: Санкт-Петербург
После разделения темы код на Аде оказался на предыдущей странице, поэтому дублирую его здесь, заодно поменяв порядок объявлений на алфавитный. Для коротких объявлений алфавитный порядок удобен, не вижу смысла отказываться.

Код на Аде от SII:
Код:
package Accounts is

    type Account is private;

    function Balance(Account : in Account ) return Integer;
    function Create(Initial_Balance : Money) return Account;
    procedure Deposit(Account : in out Account; Amount : in Money);
    procedure Withdraw(Account : in out Account; Amount : in Money);

private

    type Account is
        record
            Account_No : Positive;
            Balance    : Integer;
        end record;

end Accounts;

В адовском коде нет реализации объявленных процедур, поэтому я не стал писать их на Канторе.

Код на Канторе:
Код:
public class Accounts of // пакет -- это тоже класс

  public final class Account of
    public var Core:Integer Balance;
    public Deposit(Core:Money amount);
    public Withdraw(Core:Money amount);
  end;

end;

public final class Accounts:Account of
  var Core:Word accountNo;
end;

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

Объяснение "кусочности" парадоксально: оно следует из скриптовой природы Кантора. Тут несомненно сказывается наследие PL/SQL. Исходник на Канторе -- это кусочек БД, веточка или сук иерархии классов. Объектный код первичен, среда работает только с кодом из БД, а исходник -- набор объявлений для добавления в базу, то есть по сути скрипт.

Тип Account на Аде -- запись, передаваемая параметром в отдельно стоящие процедуры. В Канторе нет процедур вне классов, поэтому статические методы пришлось размещать бы во внешнем классе Accounts, что нарушает декомпозицию. Вместо этого все методы помещены в Accounts:Account, а сам класс описан как final, то есть он не содержит VMT и является аналогом записи в Аде. Тут Кантор следует идеологии C++: конечный (финальный) класс по сути является записью с методами.

Процедура Create на Аде играет роль псевдоконструктора, инициализирующего Account переданным значением, заодно устанавливая номер счета (предполагаю). В Канторе нет обычных конструкторов, поэтому вместо повторения псевдоконструктора я решил показать родной для Кантора способ.

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

Еще одно правило, основанное на переменных, -- обязательность их инициализации. Account.Balance описано без ref, то есть обязательно должно быть проинициализировано при создании объекта типа Account оператором new:
Код:
// некая анонимная функция
return new Accounts:Account of
  Balance = 100;
end;

На самом деле класс Accounts:Account не имеет реализации Deposit и Withdraw, из-за чего считается абстрактным, и код анонимной функции не скомпилируется. Решил не пороть отсебятины. Если пример на Аде будет расширен, можно продолжить этюд и на Канторе.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 25 апр 2015, 18:52 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Несколько поправок и микрохоливаров :)

1. Пакет Ады -- это не класс, это именно пакет (аналог дельфозного юнита, только с разделением заголовка пакета и тела пакета на физически разные исходные файлы). Аналогом класса является теговая запись (tagged record).

2. Конструкторов/деструкторов в Аде нет вообще, хотя, естественно, их роль кем-нибудь да выполняется (кем именно, зависит от особенностей типа -- где-то хватает "ума" у компилятора, а где-то надо писать подпрограммы, которые фактически являются конструкторами/деструкторами, хотя формально остаются обычными процедурами/функциями).

3. Как по мне, принуждение везде использовать классы -- фанатизм и зло, хотя и не столь вселенское, как гугл. Не во всех задачах ООП удобно.

4. Не понял насчёт переменной-особого вида функции. В Вашем примере как, можно присваивать этой переменной свободно? В адском примере применены процедуры как раз для того, чтобы нельзя было прямо изменить поля записи (мало ли что ещё дополнительно должно выполняться помимо простого присваивания).

5. Ещё раз как по мне: бесконечные public загромождают текст. ИМХО, это -- неудачное синтаксическое решение. (Ада, конечно, далеко не образец компактной записи, но подобной тавтологией заниматься всё ж не заставляет).


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 25 апр 2015, 22:41 
Аватара пользователя

Зарегистрирован: 28 май 2012, 23:44
Сообщения: 237
Откуда: Санкт-Петербург
SII писал(а):
1. Пакет Ады -- это не класс, это именно пакет (аналог дельфозного юнита, только с разделением заголовка пакета и тела пакета на физически разные исходные файлы). Аналогом класса является теговая запись (tagged record).

Кантор -- чистая ОО-система, в которой первичны именно классы и объекты, а всё остальное выражается через ООП, в том числе понятия модульного программирования. Для чистых ОО-систем ООП -- не модная фенечка, а способ переосмыслить предшествующие абстракции. Поэтому единицей трансляции в Канторе является класс. Думал писать об этом в продолжение темы "Hello, world!". Сам "Hello, world!" из одной строчки -- тоже класс, пусть вырожденный и неявный.

SII писал(а):
3. Как по мне, принуждение везде использовать классы -- фанатизм и зло, хотя и не столь вселенское, как гугл. Не во всех задачах ООП удобно.

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

SII писал(а):
4. Не понял насчёт переменной-особого вида функции. В Вашем примере как, можно присваивать этой переменной свободно? В адском примере применены процедуры как раз для того, чтобы нельзя было прямо изменить поля записи (мало ли что ещё дополнительно должно выполняться помимо простого присваивания).

Да, тут я налажал. Уже после отправки понял, но решил не исправлять, а дождаться отклика и признать свою ошибку. :lol:

Ведь если подумать, мой опыт разработки на Канторе пока минимален. Одно дело разрабатывать язык, а другое -- писать на этом языке. Прям системное и прикладное программирование в рамках одного проекта.

Немного поразмыслив, нашел два решения сокрытия переменной.

Во-первых, можно сделать как в Аде:
Код:
public class Accounts of

  public final class Account of
    public static out Account Create(Core:Money initialBalance);
    public Deposit(Core:Money amount);
    public Withdraw(Core:Money amount);
  end;

end;

public final class Accounts:Account of
  public var Core:Integer Balance;
  var Core:Word accountNo;
end;

// вызов, анонимная функция
return Accounts:Account.Create(100);

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

Во-вторых, если путей инициализации много и не получается абстрагировать их в разумное число функций-фабрик, можно реализовать свойство только для записи, которое вызывать внутри new. Фабрикой класса в этом случае становится сам new (как предполагалось в прошлом, неудачном решении):
Код:
public class Accounts of

  public final class Account of
    public InitialBalance(Core:Money value);
    public Deposit(Core:Money amount);
    public Withdraw(Core:Money amount);
  end;

end;

public final class Accounts:Account of
  public var Core:Integer Balance;
  var Core:Word accountNo;
end;

// вызов, анонимная функция
return new Accounts:Account of
  InitialBalance(100);
end;

Большое спасибо за задачку, теперь у меня есть пример со свойством только для записи. Истинное удовольствие -- работать по внешней постановке!

SII писал(а):
5. Ещё раз как по мне: бесконечные public загромождают текст.

С этим вообще просто. Есть группировка с ключевым словом of:
Код:
public class Accounts of

  public final class Account public of  // public поднимается сюда
    InitialBalance(Core:Money value);
    Deposit(Core:Money amount);
    Withdraw(Core:Money amount);
  end;

end;

Либо даже с inner/with inner of:
Код:
public class Accounts with inner of // распространяется на вложенные классы

  final class Account public of
    InitialBalance(Core:Money value);
    Deposit(Core:Money amount);
    Withdraw(Core:Money amount);
  end;

end;

Не стал писать так в первом примере, чтобы код не был похож на ребус. В Канторе нет слова procedure или function, и public играет их роль, особенно в примерах.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


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

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB