Основы T'Class Ады

Несколько смущенно спрашивать об этом, но я знаю, что это к лучшему. Я программирую на Аде уже много лет и свободно понимаю почти все части языка. Тем не менее, я никогда не мог понять T'Class. Чтобы позаимствовать у других, может кто-нибудь «объяснить, как будто мне пять?».

Редактировать: я купил его просто для того, чтобы иметь, но внутри содержится отличное описание и пример использования T'Class; Я имею в виду «Создание программного обеспечения и структуры данных с Ada 95» Майкла Б. Фельдмана.


ada
person Patrick Kelly    schedule 12.02.2015    source источник


Ответы (2)


Если вы начнете с

package P1 is
   type T is tagged private;
   procedure Method (Self : T);
end P1;
package P2 is
   procedure Proc (Self : T);  -- not a primitive
   procedure Proc2 (Self : T'Class);
end P2;

В случае с Proc вы сообщаете компилятору, что параметр всегда следует рассматривать именно как тип T (помните, что тегированный тип всегда передается по ссылке, так что фактический тип может быть получен из T, конечно, вы бы этого не сделали). потерять лишние данные). В частности, это означает, что в теле Proc все вызовы метода будут точно вызовами P1.Method, а не вызовом переопределяющего метода.

В случае с Proc2 вы сообщаете компилятору, что вы не знаете точный тип статически, поэтому ему нужно будет вставить дополнительный код для решения проблем во время выполнения. Вызов Method в теле Proc2 может быть вызовом P1.Method или другого переопределяющего метода.

По сути: с классом все решается во время выполнения.

person manuBriot    schedule 12.02.2015
comment
Однако я, кажется, запутался, если я получаю T, создавая дочерний T2, не могу ли я использовать как Proc, так и Proc2 с экземплярами T2 в качестве аргумента? Если я вас правильно понял, если T2 переопределяет метод, то T2.Proc фактически вызовет T.Method, а T2.Proc2 вызовет T2.Method. - person Patrick Kelly; 12.02.2015
comment
Да, вы можете использовать как Proc, так и Proc2 (хотя в случае Proc вам придется привести: Proc(T (Var)). Различия возникают, когда proc выполняет вызов метода, так как в этом случае будет вызвана другая подпрограмма. два случая (при условии, что T2 переопределяет метод). Ваше понимание диспетчеризации правильное (за исключением того, что вы не можете вызывать T2.Proc для T2.Proc2, только Proc2 (T2), это не примитивная операция. - person manuBriot; 13.02.2015
comment
Нет, не верю. Прежде всего, T2 здесь — это имя типа, и мы не можем использовать T2.Proc для типа. Предположим, что первоначальный автор имел в виду Var.Proc2, где Var имеет тип T2. Затем Var.Proc2 разрешен только в том случае, если Proc2 определен в том же пакете, что и T2, в противном случае запись через точку не применяется. В моем примере Proc2 определен в другом пакете, поэтому вы не можете использовать Var.Proc2. - person manuBriot; 15.02.2015
comment
Я знаю, что T2 - это название типа: я просто следил за вашим комментарием! Посмотрите на этот пример (грызть, затем грызть): Main радостно вызывает Childsprint.Prints, даже если Parents не виден. - person Simon Wright; 15.02.2015
comment
Да, конечно. Prints определяется в пакете Parents, как и тип Parent. Таким образом, вы действительно можете использовать .Prints для любого типа, производного от Parent. Но в нашем примере в этом потоке Proc2 определен в пакете, отличном от типа T, и поэтому вы не можете использовать .Proc2. - person manuBriot; 16.02.2015

Что ж, если бы вам было пять лет, я бы сказал, что T'Class представляет собой всю семью T. Под семьей мы подразумеваем детей, внуков и правнуков.

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

person Frédéric Praca    schedule 12.02.2015