Программирование на Objective-C 2.0
Шрифт:
Табл. В.8. Специальные модификаторы типов в протоколах Спецификатор Описание in Аргумент относится к объекту, значение которого будет изменено отправителем и передано (т.е. скопировано) назад получателю. out Аргумент относится к объекту, значение которого будет изменено получателем и передано назад отправителю. inout Аргумент относится к объекту, значение которого будет изменяться как отправителем, так и получателем, и будет передаваться между ними; это спецификатор по умолчанию. oneway Используется для объявлений типа возвращаемого значения; обычно используется (one way void), чтобы указать, что
Общий формат имяКласса *var1, *var2, ...;
Здесь определяются переменные varl, var2,... как объекты из класса тяКласса. Отметим, что это объявление переменных-указателей, при котором не выделяется пространство для конкретных данных, содержащихся в каждом объекте. В объявлении Fraction *myFract;
определяется myFract как объект класса Fraction или, точнее, как указатель на этот объект. Чтобы фактически выделить пространство для структуры данных класса Fraction, нужно вызвать обычно alloc или новый метод для этого класса, например, myFract = [Fraction alloc];
В результате для объекта типа Fraction будет выделен достаточный обьем па-мяти и возвращен указатель на этот объект, который будет присвоен переменной myFract. Переменную myFract часто называют объектом или экземпляром класса Fraction. Если метод alloc определен в корневом объекте, всем переменным эк-земпляра нового выделяемого объекта присваивается значение 0. Но это не оз-начает, что объект инициализирован должным образом; прежде чем использовать этот объект, для него должен быть вызван какой-либо метод инициализации (например, init).
Поскольку переменная myFract была объявлена явным образом как объект из класса Fraction, она называется переменной со статическим контролем типа. Компилятор может проверять применение переменных со статическим контролем типа на согласованность с определением класса с точки зрения правильности использования методов, а также типов их аргументов и возвращаемых значений. Объявление объекта с типом id
Общий формат id <протокол,...> varl, var2, ...;
Здесь объявляются переменные varl, var2,... как объекты из неопределенного класса, который подчиняется протоколам, перечисленным в угловых скобках. Список протоколов не является обязательным.
Переменным типа id можно присваивать объекты из любого класса, и наоборот. Если указаны один или несколько протоколов, компилятор проверяет, что методы, используемые из перечисленных протоколов для любой из объявленных переменных, используются соответствующим образом, то есть в соответствии с типами аргументов и возвращаемых значений для методов, объявленных в формальном протоколе.
Например, в строках id <MathOps> number; result = [number add: number2];
компилятор проверяет, определяется ли метод add: в протоколе athOps. Если да, то компилятор проверяет для этого метода согласованность с типами аргументов и возвращаемого значения. Например, если метод add: принимает целый аргумент, а вы передаете ему объект класса Fractior, то компилятор выводит соответствующее сообщение.
Система следит за классом, которому принадлежит каждый объект; поэтому
на этапе выполнения она может определить класс объекта и затем выбрать для вызова подходящий метод. Эти две процедуры называются соответственно динамическим контролем типов (dynamic typing) и динамическим связыванием (dynamic binding). Выражения с сообщениями Формат 1 [получатель имя1: арг1 имя2: арг2, имяЗ: аргЗ.. ]Выполняется вызов метода имя!:имя2:имяЗ из класса, указанного получателем, и значения арг1, арг2,... передаются как аргументы. Эго называется выражением с сообщением (message expression). Значением выражения является значение, воз-вращаемое методом, или void, если метод объявлен соответствующим образом и не возвращает никакого значения. Тип этого выражения совпадает с типом, объявленным для вызываемого метода. Формат 2 [получатель имя];
Если метод не принимает никаких аргументов,то этот формат используется для вызова метола имя из класса, указанного получателем.
Если получатель имеет тип id, то компилятор ищет среди объявленных классов определение или наследуемое определение указанного метода. Если не найдено такого определения, компилятор выводит предупреждение, что получатель не ответит на указанное сообщение. Кроме того, предполагается, что метод возвращает значение типа id и преобразует любые аргументы типа float в тип double, а также выполняет целочисленное расширение для любых целых аргументов, как описано выше в разделе «Преобразование базовых типов данных». Другие аргументы метода передаются без преобразования.
Если получатель является объе кто м - классом (который можно создать, просто указав имя класса), то вызывается указанный метод класса. В противном случае получатель является экземпляром класса, и тогда вызывается соответствующий метод экземпляра.
Если получатель является переменной или выражением со статическим конт-ролем типа, то компилятор ищетметод в определении класса (или среди любых наследуемых методов) и преобразует любые аргументы (когда это возможно), чтобы он и соответствовали ожидаемым аргументам данного метода. Например, если метод должен получать значение с плавающей точкой и ему передано значение целого тина, соответствующий аргумент автоматически преобразуется при вызове этого метода.
Если получатель является указателем на null-объект, то есть nil, ему тоже можно передавать сообщения. Если метод, связанный с сообщением, возвращает объект, то выражение с этим сообщением дает значение nil. Если метод не возвращает какого-либо объекта, то значение этого выражения не определено.
Если один и тот же метод определен более чем в одном классе (путем явного определения или врезультате наследования), компилятор проверяет среди этих классов соответствие типам аргументов и возвращаемою значения.
Все аргументы передаются методу по значению, поэтому их значения не могут быть изменены методом. Если методу передается указатель, то метод может изменять значения, на которые ссылается этот указатель, но метод все же не может изменять значение самого указателя. Формат 3 получатель.свойство
Это вызов getter-метода, то есть метода-получателя (по умолчанию свойство) для получателя, если выражение не используется как lvalue-выражение (см. Формат 4). Имя getter-метода можно изменять с помощью директивы @property, и тогда это будет вызываемый метод.