Шрифт:
Внесите изменения в программу 7.6, чтобы выводить результирующую сумму (sum) как дробь, а не только как вещественное число.
Будет ли ваш класс Fraction работать с отрицательными дробями? Например, можно ли сложить -1/4 и -1/2 и получить правильный результат? Напишите тестовую программу, чтобы проверить свой ответ.
Внесите изменения в метод print класса Fraction, чтобы выводить дроби, превышающие 1, как смешанные числа (с целой и дробной частями), например, дробь 5/3 выводить как 1 2/3.
В упражнении 6 главы 4 определяется новый класс с именем Complex для работы с комплексными мнимыми числами. Добавьте новый метод с именем add:, который можно использовать для сложения двух комплексных чисел. Чтобы сложить два комплексных числа, нужно по отдельности сложить вещественные и мнимые части: (5.3 + 7i) + (2.7 + 4i) = 8 + 11i Этот метод add: должен сохранять и возвращать результат в виде нового числа типа Complex в соответствии с объявлением метода: -(Complex *) add: (Complex *) complexNum; Учтите в тестовой программе все потенциальные проблемы утечки памяти.
Для класса Complex, разработанного в упражнении 6 главы 4, с учетом расширения, сделанного в упражнении 6 этой главы, создайте отдельные файлы секций interface и implementation —Complex.h и Complex.m. Создайте отдельный файл тестовой программы.
Глава 8. Наследование
В этой главе рассматривается один из ключевых принципов, который делает объектно-ориентированное программирование столь мощным. Принцип наследования позволяет расширять существующие определения классов и настраивать их для приложений. 8.1. Все начинается с корня
Мы уже рассматривали идею родительского класса в главе 3. Родительский класс может быть дочерним классом другого родительского класса. Класс, не имеющий никакого родительского класса, находится вверху иерархии и называется корневым классом (root class). В Objective-C вы можете определять собственный родительский класс, но обычно используют возможности существующих классов. Все классы, которые мы определяли до настоящего момента, являются дочерними классами (потомками) корневого класса с именем NSObject, который указывался в файле секции interface следующим образом: @interface Fraction: NSObject @end
Класс Fraction образуется из класса NSObject. Поскольку NSObject находится вверху иерархической структуры (то есть над ним уже нет никаких классов), он называется корневым классом (рис. 8.1). Класс Fraction является дочерним (child) классом или подклассом (subclass).
Рис. 8 .1. Корневой класс и подкласс
С точки зрения терминологии, можно говорить о классах, родительских классах и дочерних классах или о классах, подклассах и суперклассах. Если определяется какой-либо новый класс (не корневой), он наследует определенные свойства. Например, все переменные экземпляра и методы из родительского класса неявным образом становятся частью определения нового класса. Это означает, что соответствующий подкласс имеет непосредственный доступ к методам и переменным экземпляра, как будто они были определены непосредственно в определении этого подкласса.
Проиллюстрируем концепцию наследования с помощью простого (хотя и несколько надуманного) примера. Рассмотрим объявление объекта ClassA, содержащего один метод с именем initVar. @interface ClassA: NSObject { int x; } -(void) initVar; (@end
Метод initVar просто присваивает значение 100 переменной экземпляра класса ClassA. @implementation ClassA -(void) initVar { x = 100; } @end
Теперь определим класс с именем ClassB. @interface ClassB: ClassA -(void) printVar; @end
В первой строке этого объявления @interface ClassB: ClassA
указывается, что ClassB объяслвается не как подкласс NSObject, а как подкласс класса ClassA. И хотя родительским классом (суперклассом) для класса ClassA является NSObject, родительским классом для ClassB является ClassA (рис. 8.2). На этом рисунке корневой класс не имеет суперкласса, a ClassB, который находится внизу иерархии, не имеет подкласса. Тем самым ClassA является подклассом NSObject, ClassB является подклассом класса ClassA, а также класса NSObject (он является его «подподклассом», или внуком). Кроме того, NSObject является суперклассом для ClassA, который является суперклассом для ClassB. NSObject является также суперклассом для ClassB.
Ниже приводится полное определение для ClassB, где определяется один метод с именем printVar. @interface ClassB: ClassA -(void) printVar; @end (^implementation ClassB -(void) printVar { NSLog (@"x = %i", x); } @end
Метод printVar выводит значение переменной экземпляра х, и при этом мы не определяем никаких переменных экземпляра в ClassB. Поскольку ClassB является подклассом для ClassA, он наследует все переменные экземпляра из ClassA (в данном случае — только одну переменную). Это показано на рис. 8.3.