К. Арнольд, Д. Гослинг - Язык программирования Java (1160779), страница 55
Текст из файла (страница 55)
Кроме того, в понятие контракта входит исемантика этих операций, даже несмотря на то, что она может быть описана лишь в документации. Два метода могут иметь одинаковые имена исигнатуры, но они не будут эквивалентными, если обладают различной семантикой. Например, нельзя предположить, что каждый метод сименем print предназначен для вывода копии объекта.
Кто-нибудь может создать метод print и вложить в его название иную семантику —скажем, термин может быть сокращением от выражений “process interval” или “prioritize nonterminals”. Контракт (то есть совокупность сигнатурыи семантики) определяет сущность метода.На вопрос “как” отвечает класс, на основе которого создавался данный объект. Класс определяет реализацию методов, поддерживаемыхобъектом. Каждый объект представляет собой экземпляр класса. При вызове метода объекта выполняемый код ищется в классе. Объект можетиспользовать другие объекты, однако мы начнем изучение с простых классов, в которых все методы реализуются непосредственно.2.1.
Простой классОсновными компонентами класса являются поля (данные) и методы (код для работы с ними). Приведем простой класс Body, предназначенныйдля хранения сведений о небесных телах:class Body {public long idNum;public String nameFor;public Body orbits;public static long nextID = 0;}Прежде всего объявляется имя класса. Объявление класса в языке Java создает имя типа, так что в дальнейшем ссылки на объекты этого типамогут объявляться следующим образом:Body mercury;Подобное объявление указывает на то, что mercury является ссылкой на объект класса Body.
Оно не создает сам объект, а лишь объявляет ссылкуна него. Первоначально ссылка имеет значение null, и объект, на который ссылается mercury, не существует до тех пор, пока вы не создадите егоявным образом; в этом отношении Java отличается от других языков программирования, в которых объекты создаются при объявлениипеременных.Первая версия класса Body спроектирована неудачно. Это было сделано намеренно: по мере усовершенствования класса в данной главе мысможем сосредоточить свое внимание на некоторых возможностях языка.Упражнение 2.1Напишите простой класс Vehicle (транспортное средство) для хранения информации об автомашине, в котором предусмотрены (как минимум)поля для задания текущей скорости, текущего направления в градусах и имени владельца.Упражнение 2.2Напишите класс LinkedList (связный список), в котором имеется поле типа Object и ссылка на следующий по списку элемент LinkedList.2.2. ПоляПеременные класса называются полями; примерами могут служить поля nameFor и orbits, входящие в класс Body.
Каждый объект Body обладаетотдельным экземпляром своих полей: значение типа long отличает данное небесное тело от остальных, переменная типа String содержит егоимя, а ссылка на другой объект Body определяет небесное тело, вокруг которого оно обращается.Наличие у каждого объекта отдельного экземпляра полей означает, что его состояние уникально. Изменение поля orbits в одном объекте классаBody никак не отражается на значениях соответствующего поля в других объектах этого класса.Тем не менее иногда бывает необходимо, чтобы один экземпляр поля совместно использовался всеми объектами класса.
Такие поляобъявляются с ключевым словом static и называются статическими полями, или переменными класса. При объявлении в классе поля static всеобъекты этого класса разделяют одну и ту же копию статического поля.В нашем случае класс Body содержит одно статическое поле — nextID, в котором хранится следующий используемый идентификатор небесноготела. При инициализации класса, которая происходит после его загрузки и компоновки, в поле nextID заносится нулевое значение.
Ниже мыубедимся, что текущее значение nextID присваивается идентификатору каждого вновь создаваемого объекта класса Body.Когда в этой книге используются термины “поле” или “метод”, обычно имеются в виду нестатические поля и методы. В тех случаях, когда контекстне дает однозначного толкования, мы будем пользоваться термином “нестатическое поле” или “нестатический метод”.Упражнение 2.3Включите в класс Vehicle (транспортное средство) статическое поле для хранения идентификатора машины, а в класс Car (автомобиль) —нестатическое поле, содержащее номер машины.2.3. Управление доступом и наследованиеКод класса всегда может обращаться ко всем полям и методам данного класса.
Для управления доступом к ним из других классов, а также дляуправления наследованием их в подклассах члены классов могут объявляться с одним из четырех атрибутов доступа:●●●●Открытый (Public): к членам класса всегда можно обращаться из любого места, в котором доступен сам класс; такие члены наследуются вподклассах.Закрытый (Private): доступ к членам класса осуществляется только из самого класса.Защищенный (Protected): к данным членам разрешается доступ из подклассов и из функций, входящих в тот же пакет. Такие членынаследуются подклассами.
Расширение объектов (наследование) подробно рассмотрено в главе 3.Пакетный: доступ к членам, объявленным без указания атрибута доступа, осуществляется только из того же пакета. Такие членынаследуются подклассами пакета. Пакеты рассматриваются в главе 10.Поля класса Body были объявлены с атрибутом public, потому что для выполнения поставленной задачи программистам необходим доступ к этимполям. На примере более поздних версий класса Body мы убедимся, что подобное решение обычно является неудачным.2.4. Создание объектовДля первой версии класса Body создание и инициализация объектов, представляющих небесные тела, происходит следующим образом:Body sun = new Body();sun.idNum = Body.nextID++;sun.nameFor = “Sol”;sun.orbits = null; // Солнце является центром Солнечной// системыBody earth = new Body();earth.idNum = Body.nextID++;earth.nameFor = “Earth”;earth.orbits = sun;Сначала мы объявили две ссылки (sun и earth) на объекты типа Body.
Как упоминалось выше, объекты при этом не создаются — лишьобъявляются переменные, которые ссылаются на объекты. Первоначальное значение ссылок равно null, а соответствующие им объекты должныявным образом создаваться в программе.Объект sun создается посредством оператора new. Конструкция new считается самым распространенным способом построения объектов(позднее мы рассмотрим и другие возможности). При создании объекта оператором new следует указать тип конструируемого объекта инеобходимые параметры. Runtime-система выделяет область памяти, достаточную для хранения полей объекта, и инициализирует ее всоответствии с рассматриваемыми ниже правилами.
После завершения инициализации runtime-система возвращает ссылку на созданный объект.Если системе не удается выделить память, достаточную для создания объекта, она может запустить сборщик мусора, который освобождаетнеиспользуемую память. Если же и после этого памяти все равно не хватает, оператор new возбуждает исключение OutOfMemoryError.Создав новый объект Body, мы инициализируем его переменные. Каждый объект класса Body должен иметь уникальный идентификатор,который он получает из статического поля nextID. Программа наращивает значение nextID, чтобы идентификатор следующего объекта Bodyтакже был уникальным.В нашем примере строится модель Солнечной системы.
В ее центре находится Солнце, поэтому полю orbits объекта sun присваивается значениеnull — у Солнца нет объекта, вокруг которого оно бы вращалось. При создании и инициализации объекта earth (Земля) мы присвоили полю orbitsзначение sun. Для Луны, вращающейся вокруг Земли, поле orbits получило бы значение earth. Если бы мы строили модель Галактики, то Солнцебы также вращалось вокруг “черной дыры”, находящейся где-то в середине Млечного Пути.Упражнение 2.4Напишите для класса Vehicle метод main, который создает несколько объектов-автомашин и выводит значения их полей.Упражнение 2.5Напишите для класса LinkedList метод main, который создает несколько объектов типа Vehicle и заносит их в список.2.5. КонструкторыКаждый вновь созданный объект обладает некоторым исходным состоянием. Значения полей могут инициализироваться при их объявлении —иногда этого бывает достаточно.