Как связать классы в java
Перейти к содержимому

Как связать классы в java

  • автор:

Как связать классы в java

1 Использование интерфейсов — классы могут реализовывать интерфейсы, которые определяют набор методов, которые класс должен реализовать. Интерфейсы используются для реализации полиморфизма, то есть возможности использовать объекты разных классов, которые реализуют один и тот же интерфейс, в качестве аргументов методов или элементов массива.

Для связывания классов и интерфейсов используется ключевое слово implements . Если класс реализует интерфейс, он должен реализовать все методы, определенные в интерфейсе.

Рассмотрим пример: у нас есть интерфейс Animal , который определяет методы для работы с животными. Класс Dog реализует интерфейс Animal и реализует методы интерфейса.

interface Animal  void eat(); void sleep(); > class Dog implements Animal  public void eat()  System.out.println("Dog is eating"); > public void sleep()  System.out.println("Dog is sleeping"); > > 
  • Здесь мы определяем интерфейс Animal , который имеет два абстрактных метода eat() и sleep() .
  • Затем мы определяем класс Dog , который реализует интерфейс Animal и реализует оба метода.

Когда мы создаем объект Dog , мы можем вызывать методы eat() и sleep() , определенные в интерфейсе Animal

Dog myDog = new Dog(); myDog.eat(); // => Dog is eating myDog.sleep(); // => Dog is sleeping 

Ключевое слово implements позволяет связать класс и интерфейс. Если класс реализует несколько интерфейсов, они перечисляются через запятую в списке implements

interface Animal  void eat(); > interface Sleepable  void sleep(); > class Dog implements Animal, Sleepable  public void eat()  System.out.println("Dog is eating"); > public void sleep()  System.out.println("Dog is sleeping"); > > 

Здесь класс Dog реализует два интерфейса Animal и Sleepable

Классы и объекты

Java — это объектно-ориентированный язык, поэтому код в ваших программах будет состоять из объектов и классов.

Классы

Java позволяет создавать классы, которые представляют объекты из реального мира. Например, можно создать класс Car (автомобиль) или Animal (животное) и задать им различные свойства. Для класса Car логично создать такие свойства как двери, колёса, лобовое стекло и т.д. Имея класс Car, можно создать новые классы Легковушки, Грузовики, Автобусы, которые будут иметь все свойства класса Car, а также свои собственные свойства. У класса Animal соответственно можно задать свойства Лапы, Хвост, а затем создать наш любимый класс Cat, у которого будет ещё дополнительное свойство Усы. Иными словами, классы могут наследовать свойства от других классов. Родительский класс называется суперклассом. Внутри классов могут быть объявлены поля и методы.

Для объявления класса служит ключевое слово class. Вспомним стандартную строчку кода из Android-проекта:

 public class MainActivity extends Activity < // код внутри класса >

Упрощённая общая форма для класса может иметь следующий вид:

 class ИмяКласса < тип переменная_экземпляра1; тип имяМетода(список параметров)< // тело метода >> 

В Java принято начинать имена класса с большой буквы. В классе могут быть несколько переменных и методов. Переменные, определённые внутри класса (не метода), называются переменными экземпляра или полями (fields). Код пишется внутри класса. Методы и переменные внутри класса являются членами класса.

Объекты

Новый объект (или экземпляр) создаётся из существующего класса при помощи ключевого слова new:

 Cat barsik = new Cat(); // создали кота из класса Cat 

В большинстве случаев вы будете использовать такой способ. Пусть вас не удивляет, что приходится дважды использовать слово Cat, оно имеет разный смысл.

Слева от оператора присваивания = определяется имя переменной и его тип Cat. В правой части выражения происходит выделение памяти для нового экземпляра класса Cat и инициализируется экземпляр. Оператор присваивания присваивает переменной ссылку на только что созданный объект. Имена объектов не нужно начинать с большой буквы, как у класса. Так вы будете различать, где класс, а где экземпляр класса. Если имя экземпляра класса состоит из нескольких слов, то используется верблюжья нотация, когда все первые буквы слов, кроме первой, пишутся с большой — superBlackCat.

Если вы помните, при объявлении примитивных типов мы указывали нужный тип в самом начале.

 int catAge; 

Поэтому код Cat barsik также определяет его тип. Он не всегда может совпадать с именем класса.

 Pet barsik = new Cat(); 

В этом примере используется тип класса домашних любимцев Pet, а обращаемся к классу котов Cat.

Простой пример создания класса Box (коробка для кота):

 class Box < int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки >

При таком варианте Java автоматически присвоит переменным значения по умолчанию. Например, для int это будет значение 0. Но не всегда значения по умолчанию подойдут в вашем классе. Если вы создали переменную для описания количества лап у кота, то логично сразу присвоить значение 4. Поэтому считается хорошей практикой сразу присваивать нужные значения полям класса, не полагаясь на систему.

Вам нужно создать отдельный файл Box.java, в который следует вставить код, описанный выше. О том, как создавать новый файл для класса я не буду здесь расписывать.

Сам класс — это просто шаблон, заготовка. Чтобы ваше приложение могло использовать данный шаблон, нужно создать на его основе объект при помощи ключевого слова new:

 Box catBox = new Box; // создали реальный объект с именем catBox на основе шаблона Box 

Красивая получилась коробочка.

Объект catBox, объявленный в коде вашей программы, сразу займёт часть памяти на устройстве. При этом объект будет содержать собственные копии переменных экземпляра width, height, depth. Для доступа к этим переменным используется точка (.). Если мы хотим присвоить значение переменной width, то после создания объекта класса можете написать код:

 catBox.width = 400; // ширина коробки для кота 400 миллиметров 

Если мы хотим вычислить объём коробки, то нужно перемножить все значения размеров коробки:

 Box catBox = new Box(); catBox.width = 400; catBox.height = 200; catBox.depth = 250; int volume = catBox.width * catBox.height * catBox.depth; mInfoTextView.setText("Объём коробки: " + volume); 

Каждый объект содержит собственные копии переменных экземпляра. Вы можете создать несколько объектов на основе класса Box и присваивать разные значения для размеров коробки. При этом изменения переменных экземпляра одного объекта никак не влияют на переменные экземпляра другого объекта. Давайте объявим два объекта класса Box:

 Box bigBox = new Box(); // большая коробка Box smallBox = new Box(); // маленькая коробка int volume; // присвоим значения переменным для большой коробки bigBox.width = 400; bigBox.height = 200; bigBox.depth = 250; // присвоим значения переменным для маленькой коробки smallBox.width = 200; smallBox.height = 100; smallBox.depth = 150; // вычисляем объём первой коробки volume = bigBox.width * bigBox.height * bigBox.depth; mInfoTextView.setText("Объём большой коробки: " + volume + "\n"); // вычисляем объём маленькой коробки volume = smallBox.width * smallBox.height * smallBox.depth; mInfoTextView.append("Объём маленькой коробки: " + volume); 

Когда мы используем конструкцию типа Box bigBox = new Box();, то в одной строке выполняем сразу два действия — объявляем переменную типа класса и резервируем память под объект. Можно разбить конструкцию на отдельные части:

 Box bigBox; // объявляем ссылку на объект bigBox = new Box(); // резервируем память для объекта Box 

Обычно такую конструкцию из двух строк кода не используют на практике, если нет особых причин.

Когда мы используем ключевое слово new и указываем имя класса, то после имени ставим круглые скобки, которые указывают на конструктор класса. О них поговорим позже.

Ключевое слово final

Поле может быть объявлено как final (финальное). Это позволяет предотвратить изменение содержимого переменной, по сути, это становится константой. Финальное поле должно быть инициализировано во время его первого объявления.

final int FILE_OPEN = 1;

Теперь можно пользоваться переменной FILE_OPEN так, как если бы она была константой, без риска изменения их значений. Принято записывать имена заглавными буквами.

Кроме полей, final можно использовать для параметров метода (препятствует изменению в пределах метода) и у локальных переменных (препятствует присвоению ей значения более одного раза).

Также слово final можно применять к методам, чтобы предотвратить его переопределение.

 class Cat < final void meow() < System.out.println("Мяу"); >> class Kittent extends Cat < // Этот метод создать не получится void meow() < System.out.println("Да хоть гав-гав, всё равно не заведётся"); >> 

Ещё один вариант использования ключевого слова final — предотвращение наследования класса. При этом неявно всего методы класса также становятся финальными. Поэтому нельзя одновременно объявить класс абстрактным и финальным, поскольку абстрактный класс является лишь шаблоном и только его подклассы реализуют методы.

 final class Tail < // . >// Следующий класс недопустим class BigTail extends Tail < // Ошибка! Класс Хвост нельзя переопределять. >

Ключевое слово instanceof — Проверка принадлежности к классу

Иногда требуется проверить, к какому классу принадлежит объект. Это можно сделать при помощи ключевого слова instanceof. Это булев оператор, и выражение foo instanceof Foo истинно, если объект foo принадлежит классу Foo или его наследнику, или реализует интерфейс Foo (или, в общем виде, наследует класс, который реализует интерфейс, который наследует Foo).

Возьмём пример с рыбками, которые знакомы котам не понаслышке. Пусть у нас есть родительский класс Fish и у него есть унаследованные подклассы SaltwaterFish и FreshwaterFish. Мы можем протестировать, относится ли заданный объект к классу или подклассу по имени

 SaltwaterFish nemo = new SaltwaterFish(); if(nemo instanceof Fish) < // рыбка Немо относится к классу Fish // это может быть класс Fish (родительский класс) или подкласс типа // SaltwaterFish или FreshwaterFish. if(nemo instanceof SaltwaterFish) < // Немо - это морская рыбка! >> 

Данная проверка удобна во многих случаях. В Android очень много классов, которые происходят от класса ViewTextView, CheckBox, Button, имеющие свои собственные наборы свойств. И если имеется метод с параметром View, то при помощи instanceof можно разделить логику кода:

 void checkforTextView(View view) < if(view instanceof TextView) < // Код для элемента TextView >else < // Для других элементов View >> 

import — Импорт класса

Оператор import сообщает компилятору Java, где найти классы, на которые ссылается код. Любой сложный объект использует другие объекты для выполнения тех или иных функций, и оператор импорта позволяет сообщить о них компилятору Java. Оператор импорта обычно выглядит так:

import ClassNameToImport;

За ключевым словом import следуют класс, который нужно импортировать, и точка с запятой. Имя класса должно быть полным, то есть включать свой пакет. Чтобы импортировать все классы из пакета, после имени пакета можно поместить .*.

В Android Studio импорт класса происходит автоматически при наборе кода. Также это срабатывает и при вставке кода. Если имена классов совпадают, то студия может запросить помощь. Тогда вам нужно вручную указать нужное полное имя класса.

Импорт позволяет избежать долгого набора имени класса. Без импорта нам пришлось бы писать все классы в коде программы полностью.

 ru.alexanderklimov.MyClass.Cat.sayMeow(); java.lang.System.out.println("Мяу"); 

Статический импорт

Существует ещё статический импорт, применяемый для импорта статических членов класса или интерфейса. Это позволяет сократить количество кода. Например, есть статические методы Math.pow(), Math.sqrt(). Для вычислений сложных формул с использованием математических методов, код становится перегружен. К примеру, вычислим гипотенузу.

 hypot = Math.sqrt(Math.pow(side1, 2) + Math.pow(side2, 2)); 

В данном случае без указания класса не обойтись, так как методы статические. Чтобы не набирать имена классов, их можно импортировать следующим образом:

 import static java.lang.Math.sqrt; import static java.lang.Math.pow; . hypot = sqrt(pow(side1, 2) + pow(side2, 2)); 

После импорта уже нет необходимости указывать имя класса.

Второй допустимый вариант, позволяющий сделать видимыми все статические методы класса:

 import static java.lang.Math.*; 

В этом случае вам не нужно импортировать отдельные методы. Но такой подход в Android не рекомендуется, так как требует больше памяти.

Класс Class

На первый взгляд, класс Class звучит как «масло масляное». Тем не менее, класс с таким именем существует и он очень полезен.

Программно получить имя класса

Иногда из программы нужно получить имя используемого класса. Для этого есть специальные методы getClass().getName() и другие родственные методы. Допустим, нам нужно узнать имя класса кнопки, на которую мы нажимаем в программе.

 public void onClick(View view) < String className = view.getClass().getName(); String simpleName = view.getClass().getSimpleName(); String canonicalName = view.getClass().getCanonicalName(); if (canonicalName == null) < canonicalName = "null"; >String s = "Имя класса: " + className + "\n" + "SimpleName: " + simpleName + "\n" + "CanonicalName: " + canonicalName + "\n"; mInfoTextView.setText(s); > 
 Имя класса: android.support.v7.widget.AppCompatButton SimpleName: AppCompatButton CanonicalName: android.support.v7.widget.AppCompatButton 

getSimpleName() возвращает только имя класса без пакета, другие методы вернут полное название.

Если нужно узнать имя класса активности, то достаточно кода:

 // подставьте имя вашей активности String className = MainActivity.class.getName(); 

Если вам известно имя класса, то можете получить сам класс:

 try < // получим объект Class ClassmyClass = Class.forName("ru.alexanderklimov.test.MainActivity"); mInfoTextView.setText(myClass.getName()); // выводим в TextView Intent intent = new Intent(this, myClass); startActivity(intent); > catch (ClassNotFoundException e) < // TODO Auto-generated catch block e.printStackTrace(); >

Метод getSuperclass() возвращает имя суперкласса. Остальные несколько десятков методов не столь популярны.

Отношения в классах Java

При работе с классами и объектами в Джаве иногда возникают некоторые трудности. Несмотря на это, логика в объектно-ориентированном программировании достаточно простая. Она гласит о правилах и отношениях между классами и иными компонентами кода.

В данной статье будет рассказано о том, что собой представляет агрегация и композиция. О наследовании тоже нельзя забывать. Все это – «база», без которой создать качественное приложение не получится.

Класс и объект – понятия

В Google полно информации о том, как грамотно подойти к изучению Джавы. Но перед углубленным изучением языка требуется изучить базовые понятия и определения.

Ни одна программа немыслима без классов, а также objects. Class в Java – это своеобразный шаблон, который помогает создавать объекты. Объект выступает в виде экземпляра класса. Такие определения выдает Google.

Также стоит отметить, что:

  1. В Java class помогает определять структуру и поведение, совместно использующиеся относительно набора objects.
  2. В классе, согласно Google, содержатся переменные и методы. Это – элементы или члены.
  3. Class – база инкапсуляции в Джаве.
  4. У каждого объекта, заданного class, есть структура и поведение, определенные классом заранее.

При работе с этими компонентами будущего приложения необходимо использовать методы. Они помогают описывать то, что объект способен делать. Иногда – какие операции и манипуляции с ним разрешено выполнять. Переменные здесь описывают свойства и характеристики objects.

Создание

Вот так, согласно Google, можно создать класс в Java:

После ключевого слова class принято прописывать его имя. Далее в кавычках указываются переменные и методы. Их конкретное количество не определено.

А вот еще один пример – описание public class для объекта Box. Example предусматривает три ключевые характеристики: ширину, высоту, глубину. Они описаны через переменные:

В случае с objects требуется воспользоваться таким оператором:

Google указывает на то, что при создании соответствующего элемента процедура проходит в несколько этапов:

  1. Сначала осуществляется объявление переменной типа класса. Она не будет определять object. Google указывает, что это необходимо для установки переменной, которая умеет ссылаться на объект.
  2. Далее происходит непосредственное создание ранее упомянутого компонента кода. Через оператор new динамически будет зарезервирована память для object, после чего произведется возврат ссылки на него.

После объявления объекта класса Box все переменные класса, по Google, получат значение по умолчанию для заданного типа информации. Для обращения к переменным и дальнейшей работы с ними применяется имя переменной object:

Этой основы хватит для общего понимания выбранного направления. В объектно-ориентированном программировании существуют различные отношения между классами: агрегация и композиция, ассоциация, а также наследование. Каждый предусматривает свои ключевые особенности, о которых должен знать разработчик.

Ассоциации

Ассоциация – когда объекты двух классов ссылаются друг на друга. Они имеют между собой своеобразную связь. Пример – работник может выписать счет. Это влечет за собой ассоциацию между «участниками процесса». Еще один наглядный пример – преподаватели и студенты. Какой-то студент будет учиться у определенного преподавателя.

Ассоциация по Google – это описание связи между двумя определенными objects. Концепция здесь простая: есть объекты, которые могут быть связаны между собой. И эти связи требуется как-то описывать.

Aggregation и composition

Агрегация и композиция, если верить Google – это частный случай ассоциации. Представлены конкретизированными отношениями между objects в имеющемся исходном коде.

Тут стоит запомнить следующее:

  1. Агрегация – отношение, когда один объект выступает в качестве части другого. Пример – ученик входит в группу любителей химии.
  2. Композиция – более жесткий вариант. Object здесь не только относится к другому “похожему компоненту», но и не может иметь отношение к другим. Пример – машина и двигатель. Второй элемент способен выступать без автомобиля, но он не сможет находиться одновременно в нескольких транспортных средствах. А студенты способны посещать различные группы по интересам одновременно.

Все это – условное описание, которое дает Google. Но за счет него даже новичок сможет достаточно быстро разобраться, с чем ему предстоит иметь дело.

Примеры кодов

Чтобы позиции относительно рассматриваемого направления были быстро поняты, лучше рассмотреть наглядные примеры. Их очень много в Google. Почти все они выступают в качестве тривиальных.

Примеры основываются на следующих принципах:

  1. В пределах одного класса создается ссылка на другой и наоборот. Второй вариант встречается не всегда.
  2. Осуществляется развитие заданной идеи в зависимости от имеющихся связей. У машины 4 колеса, она будет со всеми связана. Это значит, что авто имеет ссылку на список колес (или так называемый массив).
  3. В примере нужно соединить робота с оператором его управления. Для этого используется не агрегирование, а ассоциации через ссылки в одном классе на другой.
  4. Robot будет иметь ссылку на класс Operator. Обратный вариант тоже присутствует.

Так описывается Robot:

А вот – Operator:

Допустимо создавать ссылки только в одном классе. Тогда связи односторонние. А можно ссылаться на массив или список, но ключевая концепция не меняется.

Наследование

Еще один вариант отношений – это ключевая концепция ООП. Речь идет о наследовании. Оно представляет собой своеобразный механизм при помощи которого удается описывать новые классы на основе уже существующего (родителя). Свойства и функциональность родительского класса, по Google, будут заимствованы «наследником».

Здесь стоит запомнить следующие данные:

  1. Если у дочернего класса есть уникальные свойства, поля спокойно объявляются внутри него.
  2. Главное преимущество наследование – возможность повторного использования программного кода.
  3. Множественное наследование в Джаве отсутствует. Класс наследуется только от одного «родителя».

В Google можно обнаружить немало туториалов и примеров, которые лучше всего объясняют соответствующую особенность.

Особое взаимодействие

Стоит обратить внимание на еще один метод взаимодействия компонентов кода. Речь идет о ситуации, когда постоянная связь между objects отсутствует, но какие-то сведения требуется передать от одного к другому.

Для этого применяется передача object непосредственно в методе. Пример – робот имеет method, который принимает информацию от другой «машины»: координаты. Это требуется для перемещения первого.

Ситуация потребует создания метода, который в виде параметра обладает object класса Robot. Чтобы лучше понимать композицию и агрегацию, а также иные особенности программирования на Java, стоит посетить дистанционные компьютерные курсы. Они помогут без Google быстро освоить выбранное направление и набраться практического опыта.

можно ли как-то связать два исходных файла классов в java?

вот 2 класса, обведены красным

Возможно глупый вопрос, но никак не могу понять, возможно ли связать каким-либо образом два файла классов, находящихся в одном пакете?

Отслеживать
задан 18 ноя 2018 в 17:35
37 6 6 бронзовых знаков
а что имеется в виду под «связать?»
18 ноя 2018 в 17:36

в одном файле только один public-класс. Если в двух файлах только один класс объявлен как public, то можно затолкать в один общий файл все. Если оба класса public, то только в двух файлах хранить

18 ноя 2018 в 17:43

@Maxgmer например, в 1-ом файле выполняется одно какое-то действие, а во 2-ом другое и чтобы они работали вместе, в одной программе

18 ноя 2018 в 20:24

@ТимурБаймагамбетов а если оба класса public, можно ли как-то, так скажем, передать данные из 2-го класса в первый?

18 ноя 2018 в 20:27

конечно. Можно в методе одного класса вызвать Class2 class2 = new Class2(); и далее вызвать его метод class2.foo();

1 дек 2018 в 14:29

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

То что вы хотите реализовать называется зависимостью.

В простейшем случае вы можете экземпляру одного класса передать ссылку на экземпляр другого и реализовать некую зависимость:

Class Human < Dog dog; void walkWithDog(int speed) < walk(speed); dog.runAround(this, speed *2); >void walk(int speed) < // do somthing >> 

Человек выйдя гулять с собакой не просто будет ходить, но и будет выгуливать собаку, которая станет бегать вокруг него с удвоенной скоростью. Если в первом объекте выполняется действие, то и во втором выполняется действие связанное с ним, кроме того из объекта человек в объект собака переданы данные о скорости прогулки.

Вы усложняете класс Human , но заставляете собаку бегать. Есть и другие способы наладить зависимости между классами, например Аспектно-ориентированное программирование.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *