Использование полей объекта в другом классе
Есть класс Frame, в котором предыдущие классы реализованы:
И есть класс Attack, так сказать, проблемный 🙂
Вообщем вопрос: в классе Attack мне нужно использовать значения объектов play и ene. Как мне посоветовали написать: final Player play и final Enemy ene и использовать конструктор; но тогда обращение к методам гет и сет, через эти объекты дают ошибку инициализации. Если без final, то при работе программы вылетает ошибка
но тогда обращение к методам гет и сет, через эти объекты дают ошибку инициализации
ну наверное потому и выдают, что у вас play и ene не инициализированы — вы в классе Attack нигде не инициализируете эти поля, несмотря на то, что создаете сами экземпляры перед созданием Attack . Можете, например, передавать их в конструктор класса Attack , либо инициализировать их уже в нем, либо сделать для этих полей сеттеры и вызывать их — вариантов достаточно.
А вообще у вас тут есть довольно странный код: классы Player и Enemy выглядят совершенно идентичными. Отсюда возникает вопрос — зачем нужен класс Enemy , если его легко заменить классом Player ?
C++. Объекты класса как члены данных класса. Примеры
Как известно, в классах могут объявляться члены данных класса, которые являются объектами других классов. В данном примере продемонстрированы использования двух объектов, которые есть членами данных класса.
В примере объявляется 2 класса:
- класс CMyPoint , определяющий точку с координатами x , y ;
- класс CMyLine , определяющий линию содержащую два объекта типа CMyPoint . Эти объекты содержат координаты концов отрезка, из которых состоит линия.
Класс CMyPoint содержит:
- внутренние члены данных x , y ;
- конструктор по умолчанию CMyPoint() ;
- методы чтения внутренних данных класса GetX() , GetY() ;
- метод SetXY() , устанавливающий новые значения x , y .
Класс CMyLine содержит:
- внутренние члены-данных класса типа CMyPoint с именами mp1 , mp2 . Эти члены-данных есть объектами класса CMyPoint . Они определяют 2 точки, из которых состоит линия;
- конструктор по умолчанию CMyLine() ;
- методы чтения значения объектов mp1 , mp2 которые имеют соответственно имена GetPoint1() , GetPoint2() ;
- метод SetLine() для установления нового значения координат концов отрезка CMyLine ;
- метод Length(), вычисляющий длину отрезка.
Объявление и реализация методов классов CMyPoint и CMyLine
Демонстрация использования класса CMyLine
2. Каким образом выполняется вызов конструкторов, если в классе A используется объект класса B ? Каким образом выделяется память для объектов этих классов?
Если в классе A объявляется объект класса B , то при объявлении объекта класса A конструкторы обоих классов вызываются в следующей последовательности:
- конструктор класса B ;
- конструктор класса A .
Такую последовательность действий компилятор формирует автоматически.
Память для членов-данных класса, которые есть объектами класса, выделяется при выделении памяти для объекта класса, в котором эти объекты реализованы. То есть, если описать объект класса A , в котором есть объект класса B , то память для объекта класса A выделяется с учетом (включает в себя) памяти объекта класса B .
Например. Если взять класс CMyPoint , который объявлен в п. 1 этой темы, то при создании объекта класса CMyLine , сначала вызывается соответствующий конструктор класса CMyPoint (выделяется память), а затем вызывается конструктор класса CMyLine .
3. Инициализация внутреннего объекта класса с помощью конструктора. Пример
Синтаксис языка C++ позволяет проводить удобную инициализацию внутреннего объекта класса в конструкторе с использованием символа : (двоеточие) и вызова конструктора внутреннего класса.
Например, если в некотором классе OuterClass объявляется экземпляр obj другого класса InnerClass
то конструктор класса OuterClass может инициализировать этот объект по следующему вызову
Пример.
В примере демонстрируются особенности инициализации внутренних объектов типа Point , объявляемых в классе Line , а именно:
Доступ к переменной из другого класса в Java

В этом руководстве показано, как вызвать переменную из другого класса в Java. Мы включили несколько примеров программ, которым вы можете следовать при выполнении этого проекта.
Доступ к статическим переменным в Java
Переменная определяется как имя, используемое для хранения значения любого типа во время выполнения программы. В Java переменная может быть статической, локальной или экземплярной. Если переменная статическая, мы можем получить к ней доступ, используя имя класса. Если переменная является экземпляром, мы должны использовать объект класса для доступа к переменной. Давайте разберемся дальше на примерах, которые у нас есть.
В приведенной ниже программе мы получаем доступ к статической переменной класса Test в SimpleTesting , используя имя класса. Видите ли, мы не создали объект класса; так мы можем получить доступ к статическим переменным в любом месте исходного кода Java.
Доступ к переменным экземпляра в Java
Здесь мы получаем доступ к переменным экземпляра из другого класса. Видите ли, мы использовали объект класса Test для доступа к его переменной экземпляра. Вы можете получить доступ к переменным экземпляра только с помощью объекта класса. Посмотрите пример программы ниже.
Наследование
Наследование является неотъемлемой частью Java. При использовании наследования вы говорите: Этот новый класс похож на тот старый класс. В коде это пишется как extends, после которого указываете имя базового класса. Тем самым вы получаете доступ ко всем полям и методам базового класса. Используя наследование, можно создать общий класс, которые определяет характеристики, общие для набора связанных элементов. Затем вы можете наследоваться от него и создать новый класс, который будет иметь свои уникальные характеристики. Главный наследуемый класс в Java называют суперклассом. Наследующий класс называют подклассом. Получается, что подкласс — это специализированная версия суперкласса, которая наследует все члены суперкласса и добавляет свои собственные уникальные элементы. К примеру, в Android есть класс View и подкласс TextView.
Чтобы наследовать класс, достаточно вставить имя наследуемого класса с использованием ключевого слова extends:
В этом коде мы наследуемся от класса Activity и добавляем свой код, который будет отвечать за наше приложение.
Подкласс в свою очередь может быть суперклассом другого подкласса. Так например, упоминавший ранее класс TextView является суперклассом для EditText.
В производный класс можно добавлять новые методы.
Для каждого создаваемого подкласса можно указывать только один суперкласс. При этом никакой класс не может быть собственным суперклассом.
Хотя подкласс включает в себя все члены своего суперкласса, он не может получить доступ к тем членам суперкласса, которые объявлены как private.
Помните, мы создавали класс Box для коробки кота. Давайте наследуемся от этого класса и создадим новый класс, который будет иметь не только размеры коробки, но и вес.
В том же файле Box.java после последней закрывающей скобки добавьте новый код:
Возвращаемся в главную активность и пишем код:
Обратите внимание, что мы вызываем метод getVolume(), который не прописывали в классе HeavyBox. Однако мы можем его использовать, так как мы наследовались от класса Box и нам доступны все открытые поля и методы. Заодно мы вычисляем вес коробки с помощью новой переменной, которую добавили в подкласс.
Теперь у нас появилась возможность складывать в коробку различные вещи. В хозяйстве всё пригодится.
При желании вы можете создать множество разных классов на основе одного суперкласса. Например, мы можем создать цветную коробку.
Ключевое слово super
В Java существует ключевое слово super, которое обозначает суперкласс, т.е. класс, производным от которого является текущий класс. В данном случае, супер не означает превосходство, скорее даже наоборот, дочерний класс имеет больше методов, чем родительский. Само слово пошло из теории множеств, где используется термин супермножество. Посмотрим, зачем это нужно.
В конструкторе HeavyBox мы дублировали поля width,height и depth, которые уже есть в классе Box. Это не слишком эффективно. Кроме того, возможны ситуации, когда суперкласс имеет закрытые члены данных, но мы хотим иметь к ним доступ. Через наследование это не получится, так как закрытые члены класса доступны только родному классу. В таких случаях вы можете сослаться на суперкласс.
Ключевое слово super можно использовать для вызова конструктора суперкласса и для обращения к члену суперкласса, скрытому членом подкласса.
Использование ключевого слова super для вызова конструктора суперкласса
Вызов метода super() всегда должен быть первым оператором, выполняемым внутри конструктора подкласса.
При вызове метода super() с нужными аргументами, мы фактически вызываем конструктор Box, который инициализирует переменные width, height и depth, используя переданные ему значения соответствующих параметров. Вам остаётся инициализировать только своё добавленное значение weight. При необходимости вы можете сделать теперь переменные класса Box закрытыми. Проставьте у полей класса Box модификатор private и убедитесь, что вы можете обращаться к ним без проблем.
У суперкласса могут быть несколько перегруженных версий конструкторов, поэтому можно вызывать метод super() с разными параметрами. Программа выполнит тот конструктор, который соответствует указанным аргументам.
Вторая форма ключевого слова super действует подобно ключевому слову this, только при этом мы всегда ссылаемся на суперкласс подкласса, в котором она использована. Общая форма имеет следующий вид:
Здесь член может быть методом либо переменной экземпляра.
Подобная форма подходит в тех случаях, когда имена членов подкласса скрывают члены суперкласса с такими же именами.
В результате мы должны увидеть:
Таким образом, знакомое нам выражение super.onCreate(savedInstanceState) обращается к методу onCreate() из базового класса.
Создание многоуровневой иерархии
Мы использовали простые примеры, состоящие из суперкласса и подкласса. Можно строить более сложные конструкции, содержащие любое количество уровней наследования. Например, класс C может быть подклассом класса B, который в свою очередь является подклассом класса A. В подобных ситуациях каждый подкласс наследует все характеристики всех его суперклассов.
Напишем пример из трёх классов. Суперкласс Box, подкласс HeavyBox и подкласс MoneyBox. Последний класс наследует все характеристики классов Box и HeavyBox, а также добавляет поле cost, которое содержит стоимость коробки.
Box.java
HeavyBox.java
MoneyBox
Код для основной активности, например, при щелчке кнопки:
В результате мы получим различные значения, вычисляемые в коде. Благодаря наследованию, класс MoneyBox может использовать классы Box и HeavyBox, добавляя только ту информацию, которая нам требуется для его собственного специализированного применения. В этом и состоит принцип наследования, позволяя повторно использовать код.
Метод super() всегда ссылается на конструктор ближайшего суперкласса в иерархии. Т.е. метод super() в классе MoneyBox вызывает конструктор класса HeavyBox, а метод super() в классе HeavyBox вызывает конструктор класса Box.
Если в иерархии классов конструктор суперкласса требует передачи ему параметров, все подклассы должны передавать эти параметры по эстафете.
В иерархии классов конструкторы вызываются в порядке наследования, начиная с суперкласса и заканчивая подклассом. Если метод super() не применяется, программа использует конструктор каждого суперкласса, заданный по умолчанию или не содержащий параметров.
Вы можете создать три класса A, B, C, которые наследуются друг от друга (A←B←C), у которых в конструкторе выводится текст и вызвать в основном классе код:
Вы должные увидеть три строчки текста, определённые в каждом конструкторе класса. Поскольку суперкласс ничего не знает о своих подклассах, любая инициализация полностью независима и, возможно, обязательна для выполнения любой инициализацией, выполняемой подклассом.
Переопределение методов
Если в иерархии классов имя и сигнатура типа метода подкласса совпадает с атрибутами метода суперкласса, то метод подкласса переопределяет метод суперкласса. Когда переопределённый метод вызывается из своего подкласса, он всегда будет ссылаться на версию этого метода, определённую подклассом. А версия метода из суперкласса будет скрыта.
Если нужно получить доступ к версии переопределённого метода, определённого в суперклассе, то используйте ключевое слово super.
Не путайте переопределение с перегрузкой. Переопределение метода выполняется только в том случае, если имена и сигнатуры типов двух методов идентичны. В противном случае два метода являются просто перегруженными.
В Java SE5 появилась запись @Override; она не является ключевым словом. Если вы собираетесь переопределить метод, используйте @Override, и компилятор выдаст сообщение об ошибке, если вместо переопределения будет случайно выполнена перегрузка.
Для закрепления материала создадим класс Animal с одним методом.
Теперь создадим класс Cat, наследующий от первого класса.
Java знает, у родительского класса есть метод sleep(). Удостовериться можно следующим образом. Находясь в классе Cat, выберите в меню Source | Override/Implement Methods. . Появится диалоговое окно, где можно отметить флажком нужный метод.

В результате в класс будет добавлена заготовка:
Попробуем вызвать данный метод в основном классе активности:
Мы получим текст, который определён в суперклассе, хотя вызывали метод дочернего класса.
Но если мы хотим получить другой текст, совсем не обязательно придумывать новые методы. Достаточно закомментировать вызов метода из суперкласса и добавить свой вариант.
Запускаем программу и нажимаем на кнопку. И получим уже другой ответ, более соответствующий описанию среднестатистического кота. Заметьте, что код для щелчка кнопки мы не меняем, но система сама разберётся, что выводить нужно текст не из суперкласса, а из дочернего класса.
Рассмотрим другой пример переопределения методов. Создадим суперкласс Figure, который будет содержать размеры фигуры, а также метод для вычисления площади. А затем создадим два других класса Rectangle и Triangle, у которых мы переопределим данный метод.
Как видите, во всех классах используется одно и тоже имя метода, но каждый класс по своему вычисляет площадь в зависимости от фигуры. Это очень удобно и позволяет не придумывать новые названия методов в классах, которые наследуются от базового класса.