JavaRush /Курсы /Java Syntax Pro /Полезное

Полезное

Java Syntax Pro
19 уровень , 4 лекция
Открыта

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

Работа с игровым движком JavaRush подразумевает использование наследования. Но что делать, если вы не знаете, что это такое? С одной стороны, нужно в этой теме разобраться и изучить ее. С другой стороны, т.к. движок специально спроектирован очень простым, там можно обойтись поверхностным знанием наследования.

Итак, что же такое наследование? Если говорить упрощенно, наследование — это связь между двумя классами. Один из них становится родителем, а второй — потомком (классом-наследником). При этом класс-родитель может даже не знать, что у него есть классы-потомки. Т.е. особой выгоды от наличия классов-наследников он не получает.

А вот классу-потомку наследование дает много преимуществ. И главное из них в том, что все переменные и методы класса-родителя появляются в классе-потомке, как будто код класса-родителя скопировали в класс-потомок. Это не совсем так, но для базового понимания наследования пойдет.

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

Пример 1 — самый простой пример с наследованием

public class Родитель
{
}
Класс Потомок унаследован от класса Родитель с помощью ключевого слова extends.
public class Потомок extends Родитель
{
}

Пример 2 — использование переменных класса-родителя

public class Родитель
{
  public int age;
  public String name;
}
Класс Потомок может использовать переменные age и name класса Родитель, как будто они объявлены в нем.
public class Потомок extends Родитель
{
  public void printInfo()
  {
    System.out.println(name + " " + age);
  }
}

Пример 3 — использование методов класса-родителя

public class Родитель
{
   public int age;
   public String name;
   public getName() {
      return name;
   }
}
Класс Потомок может использовать переменные и методы класса Родитель, как будто они объявлены в нем. В этом примере мы используем метод getName().
public class Потомок extends Родитель
{
   public void printInfo()
   {
      System.out.println(getName() + " " + age);
   }
}

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

public class Потомок extends Родитель
{
   public int age; // унаследованная переменная public String name; // унаследованная переменная public getName() { // унаследованный метод return name; } 
   public void printInfo()
   {
      System.out.println(getName() + " " + age);
   }
}
класс Потомок с точки зрения компилятора


2. Переопределение методов

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

Что делать в этой ситуации? Мы можем переопределить непонравившийся нам метод. Делается это очень просто: в нашем классе Потомок мы просто объявляем метод с такой же сигнатурой (заголовком), что и метод класса Родитель и пишем в нем наш код.

Пример 1 — переопределение метода

public class Родитель
{
   public String name;
   public void setName(String nameNew) {
      name = nameNew;
   }

   public getName() {
      return name;
   }
}
Метод printInfo() выведет на экран фразу:
Luke, No!!!
public class Потомок extends Родитель
{
   public void setName(String nameNew) {
      name = nameNew + ", No!!!";
   }

   public void printInfo()
   {
      setName("Luke");
      System.out.println(getName());
   }
}

Грубо говоря, при наследовании код класса-родителя копируется внутрь класса-потомка. Но если в классе-потомке уже есть такой же метод, как в классе-родителе, такой метод из класса-родителя не копируется. Тогда говорят, что метод класса-потомка перекрывает (переопределяет) метод класса-родителя. Посмотрите на пример ниже, возможно, станет немного понятнее:

Вот как выглядит класс Потомок с точки зрения компилятора:
public class Потомок extends Родитель
{
   public String name; // унаследованная переменная

   public void setName(String nameNew)  // переопределенный метод взамен унаследованного
   {
      name = nameNew + ", No!!!";
   }

   public getName() // унаследованный метод { return name; }

   public void printInfo()
   {
      setName("Luke");
      System.out.println(getName());
   }
}

Пример 2 — немного магии наследования (и переопределения методов)

public class Родитель
{
   public getName() {
      return "Luke";
   }

   public void printInfo()
   {
      System.out.println( getName() );
   }
}
public class Потомок extends Родитель
{
   public getName() {
      return "I'm your father, Luke";
   }
}

Если метод printInfo() вызвать у объекта типа Родитель, он в свою очередь вызовет метод getName() класса Родитель.

Если же метод printInfo() вызвать у объекта класса Потомок, он в свою очередь вызовет метод getName() класса Потомок.

Т.е. метод printInfo() объявлен только в классе Родитель, но он будет вызывать метод getName() класса Потомок, если сам метод printInfo() вызвать у объекта типа Потомок.

Пример:

Родитель parent = new Родитель();
parent.printnInfo();
Этот код выведет на экран надпись:
Luke
Потомок child = new Потомок();
child.printnInfo();
Этот код выведет на экран надпись:
I'm your father, Luke

А все потому, что с точки зрения компилятора (очень упрощенная версия) код класса Потомок выглядит так:

public class Потомок extends Родитель
{
   public getName() {
      return "I'm your father, Luke";
   }

   public void printInfo() { System.out.println(getName()); }
}
класс Потомок с точки зрения компилятора


3. Списки

Краткое напоминание информации о списках (List). У списков есть много общего с массивами:

  • Могут хранить много данных определенного типа.
  • Позволяют получать элементы по их индексу/номеру.
  • Индексы элементов начинаются с 0.

Преимущества списков:

В отличие от массивов, списки могут динамически менять размер. Сразу после создания список имеет размер 0. По мере добавления элементов в список, его размер увеличивается. Пример создания списка

ArrayList<String> myList = new ArrayList<String>();
Создание нового списка типа ArrayList

Значение в угловых скобках — это тип данных, которые может хранить список.

Некоторые методы для работы со списком:

Код Краткое описание действий кода
ArrayList<String> list = new ArrayList<String>();
Создание нового списка строк
list.add("name");
Добавить элемент в конец списка
list.add(0, "name");
Добавить элемент в начало списка
String name = list.get(5);
Получить элемент по его индексу
list.set(5, "new name");
Изменить элемент по его индексу
int count = list.size();
Получить количество элементов в списке
list.remove(4);
Удалить элемент из списка

Для получения более подробной информации о списках, можете ознакомиться со статьями:



4. Случайные числа

У игрового движка JavaRush есть два метода, которые можно использовать для получения случайных чисел. Это методы:

int getRandomNumber(int max)
int getRandomNumber(int min, int max)

Первый метод — getRandomNumber(int max) возвращает случайное целое число в диапазоне 0, 1, 2, ... max-1. Под капотом он использует класс Random из пакета java.util, но принцип работы с генератором случайных чисел от этого не меняется.

В качестве аргумента getRandomNumber(int) принимает целое число. Это число будет верхней границей, которую может вернуть генератор случайных чисел. Нижней границей является 0. Внимание! Генератор НИКОГДА не вернёт верхнее граничное число. Например, если вызвать getRandomNumber(3) он случайным образом может вернуть 0, 1, 2. Как видно, 3 он вернуть не может. Такое использование генератора является довольно простым, но очень эффективным во многих случаях.

Второй метод — getRandomNumber(int min, int max) возвращает случайное целое число в диапазоне [min, max-1]. Он никогда не вернет число, меньше min, и никогда не вернет число, больше max-1.

Как же эти методы использовать на практике?

1. Игральные кости

Допустим, вы хотите имитировать бросок игральных костей и получить случайное число в диапазоне 1-6, как это сделать? Это можно сделать с помощью кода вида:

int dice = getRandomNumber(1, 7);

Такой метод вернет случайное целое число в диапазоне 1-6.

2. Стрельба по мишени

Допустим вам нужно имитировать выстрел по мишени, и у вашего выстрела есть случайное отклонение в диапазоне от -10 до +10 включительно. Это можно сделать с помощью кода вида:

int dx = getRandomNumber(-10, 11);

Такой метод вернет случайно целое число в диапазоне -10 до +10.

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

Играть в игры могут все, создавать их — только программисты.


Комментарии (95)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Виктор Уровень 21
22 октября 2025
Как это работает, cells ведь это ArrayList Cell-ов, а нам нужна одна клетка. Закипел. @Override public void onMouseLeftClick(int x, int y) { setCellColor(x, y, Color.ORANGE); Cell cell = new Cell (x,y); if (cell.equals(cells)){ cells.add(cell); }
Олександр Уровень 28
22 августа 2025
like
Anonymous #3585174 Уровень 33
28 июля 2025
like
4el0vek3 Уровень 36
25 июля 2025
no like?
Victor Уровень 36
17 февраля 2025
Третья задача "Работаем со списком координат" по-моему вот так более правильно, но валидатор упёрся. public void onMouseRightClick(int x, int y) { //напишите тут ваш код Cell mycell = new Cell(x, y); if (getCellColor(x, y) == Color.ORANGE) { setCellColor(x, y, Color.WHITE); cells.remove(mycell); } }
menand Уровень 26
4 декабря 2024
Не хватает информации про аннотацию @Override - и с ней и без неё работает.. гдето есть подвох..
CodeMashine Уровень 33
10 декабря 2024
это просто комментарий для тебя и разработчиков после тебя что этот метод переопределяется. я думаю так
8 апреля 2025
Это информация для компилятора, который в случае аннотации проверит, что выполнены условия оверрайда - одинаковая сигнатура метода. Если условие не выполнится, что компилятор будет ругаться. Если аннотацию не добавить, то в случае изменения сигнатуры будут доступны оба метода, а это уже оверлоад.
Сергей Уровень 25
17 сентября 2024
На 30 уроке, как понимаю, будет урок про то, как объявлять переменные
qaseqiara Уровень 25
6 октября 2024
поскорее бы дойти
GreyBeard Уровень 38
8 октября 2024
постой паровоз, не стучите колеса...
Tech Priest Уровень 23
1 сентября 2024
Вот прямь явно ощущение что вот эта лекция должна быть в начале 20-го блока
FolFix Уровень 38
14 августа 2024
Спидран по изученному
Igoreek Уровень 43
31 июля 2024
Задачка "Работаем со списком координат" хороша для отработки методов стрима, хотя хотелось завернуть в foreach
Нелли Уровень 38
27 сентября 2024
Когда решил задачу через foreach и осознал что можно было через stream
CodeMashine Уровень 33
10 декабря 2024
а я не понял как через поток. там писать то 2 и 3 строчки.(буквально)