> For the complete documentation index, see [llms.txt](https://opu.gitbook.io/oop/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://opu.gitbook.io/oop/2019-2020-archive/arkhiv-1/labs/lab_2/java.md).

# 1. Синтаксис создания классов

Создадим класс `Box`, который описывает контейнер, допустим, на каком-то складе.

{% code title="Box.java" %}

```java
public class Box {
    
    double width;
    double height;
    double depth;
    
}
```

{% endcode %}

Класс `Box` определяет три переменные экземпляра: `width` (ширина), `height` (высота) и `depth` (глубина). В настоящий момент класс `Box` не содержит ник~~а~~ких методов.

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

Чтобы действительно создать объект класса `Box`, нужно воспользоваться оператором `new`

{% code title="Main.java" %}

```java
public class Main {
    public static void main(String[] args) {

        Box myBox = new Box();
    }
}
```

{% endcode %}

После выполнения этого оператора объект `myBox` станет экземпляром класса `Box`. Таким образом, он обретет "физическое" существование.

Также следует напомнить, что каждый объект содержит собственную копию переменной экземпляра, которая определена в классе. Каждый объект типа `Box`будет содержать собственные копии переменных `width`, `height` и `depth`(рис. 4.2).

![Представление объектов в памяти](https://1377473627-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LnhxGhlv6e_zwoZYywB%2F-LoGwivMxUDik5DfehB7%2F-LoH-lTYGfxSxa5VejFO%2Fassets_-LIEGYndXIZn8whSYtWl_-LWFn5TXHsu3zjFF5qQF_-LWFoSJdUSo_2USk7CUO_image.png?alt=media\&token=01efbbd8-5b7f-49f1-869f-044fc1d7ecba)

Изменения в переменных экземпляра одного объекта не влияют на переменные экземпляра другого объекта. Таким образом, каждый объект класса `Box` будет содержать собственные копии переменных `width`, `height` и `depth`. Для доступа к этим переменным служит оператор-точка `(.)`. Эта операция связывает имя объекта с именем переменной экземпляра. Например, чтобы присвоить переменной `width` экземпляра `myBox` значение 100, нужно выполнить следующий оператор:

```java
myBox.width = 100;
```

Этот оператор предписывает компилятору, что копии переменной `width`, хранящейся в объектe `myBox`, требуется присвоить значение 100. В общем, операция-точка служит для доступа как к переменным экземпляра, так и к методам в пределах объекта.&#x20;

Ниже приведет пример программы, в которой используется класс `Box`

{% tabs %}
{% tab title="Main.java" %}

```java
public class Main {
    public static void main(String[] args) {

        // Создаем объект типа Box
        Box myBox = new Box();

        // Присваиваем значения переменным экземпляра myBox
        myBox.width = 10;
        myBox.height = 20;
        myBox.depth = 15;

        // Рассчитываем объем коробки
        double volume = myBox.width * myBox.height * myBox.depth;

        System.out.println("Объем равен: " + volume);
    }
}
```

{% endtab %}

{% tab title="Box.java" %}

```java
public class Box {

    double width;
    double height;
    double depth;

}
```

{% endtab %}
{% endtabs %}

Как пояснялось ранее, каждый объект содержит собственные копии переменных экземпляра. Это означает, что при наличии двух объектов класса `Box` каждый из них будет содержать собственные копии переменных `width`, `height` и `depth`. Следует, однако, иметь ввиду, что изменения в переменных экземпляра одного объекта не влияют на переменные экземпляра другого. Например, в следующей программе объявлены два объекта класса `Box`:

```java
public class Main {
    public static void main(String[] args) {

        Box myBox1 = new Box();
        Box myBox2 = new Box();

        // Присваиваем значения для mybox1
        myBox1.width = 10;
        myBox1.height = 20;
        myBox1.depth = 15;

        // Присваиваем значения для mybox2
        myBox2.width = 3;
        myBox2.height = 6;
        myBox2.depth = 9;

        double volume;

        // объем первой коробки
        volume = myBox1.width * myBox1.height * myBox1.depth;
        // будет выведено 3000
        System.out.println("Объем равен: " + volume);

        // объем второй коробки
        volume = myBox2.width * myBox2.height * myBox2.depth;
        // будет выведено 162
        System.out.println("Объем равен: " + volume);
    }
}
```

Программа выводит следующий результат:

```
Объем равен: 3000.0
Объем равен: 162.0
```

Как видите, данные из объекта `myBox1` полностью изолированы от данных, содержащихся в объекте `myBox2`.

## Методы класса

Как упоминалось ранее, классы состоят из двух компонентов: переменных экземпляра и методов. Общая форма метода выглядит следующим образом:

```
[возвращаемый тип] имя ([список параметров]) {
    [тело метода]
}
```

где `возвращаемый тип` означает конкретный тип данных, возвращаемый методом. Он может быть любым допустимым типом данных, в том числе и типом созданного класса. Если метод не возвращает значение, то его возвращаемым типом должен быть `void`. В качестве имени методов может быть любой допустимый идентификатор, кроме тех, которые уже используются другими элементами кода в текущей области действия. А `список параметров` обозначает последовательность пар "тип-идентификатор", разделенных запятыми. По существу, параметры - это переменные, которые принимают значения аргументов, передаваемых методу во время его вызова. Если у метода отсутствуют параметры, то список параметров оказывается пустым. Методы, возвращаемый тип которых отличается от `void`, возвращают значение вызывающей части программы с помощью оператора `return`.

Вернемся к нашему примеру с классом `Box`. Было бы логично, если бы расчет объема коробки выполнялся в классе `Box`, поскольку объем коробки зависит от ее размеров. Для этого добавим в класс `Box` метод `getVolume()`

{% code title="Box.java" %}

```java
class Box {

    double width;
    double height;
    double depth;
    
    void getVolume() {
        System.out.print("Объем коробки равен ");
        System.out.println(width * height * depth);
    }
}
```

{% endcode %}

Внимательно рассмотрим две следующие строки кода

```java
mybox1.volume();
mybox2.volume();
```

В первой строке вызывается метод `volume()` для объекта `myBox1`. Следовательно, метод `volume()` вызывается по отношению к объекту `myBox1`, для чего было указано имя объекта, а вслед за ним - операция-точка. Таким образом, в результате вызова метода `myBox1.volume()` выводится объем коробки, определяемого объектом `myBox1`, а в результате вызова метода `myBox2.volume()` - объем коробки, определяемого объектом `myBox2`.

При вызове метода `myBox1.volume()` исполняющая система Jаvа передает управление коду, определенному в теле метода `volume()`. По окончании выполнения всех операторов в теле метода управление возвращается вызывающей части программы и далее ее выполнение продолжается со строки кода, следующей за вызовом метода. В самом общем смысле метод - это способ реализации подпрограмм в Java.

В методе `volume()` следует обратить внимание на еще одну очень важную особенность: ссылка на переменные экземпляра `width`, `height` и `depth` делается непосредственно без указания перед ними имени объекта или операции-точки. Когда в методе используется переменная экземпляра, определенная в его же классе, это делается непосредственно, без указания явной ссылки на объект и применения операции-точки . Это становится понятным, если немного подумать. Метод всегда вызывается по отношению к какому-то объекту его класса. Как только этот вызов сделан, объект известен. Таким образом, в теле метода вторичное указание объекта совершенно излишне. Это означает, что переменные экземпляра `width`, `height` и `depth` неявно ссылаются на копии этих переменных, хранящиеся в объекте, который вызывает метод `volume()`.&#x20;

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

Следует обратить внимание, что метод `getVolume()` возвращает значение 3000, и это значение рассчитанного объема сохраняется в переменной `vol`. При обращении с возвращаемыми значениями следует принимать во внимание два важных обстоятельства:

* тип данных, возвращаемых методом, должен быть совместим с возвращаемым типом, указанным в методе. Так, если какой-нибудь метод должен возвращать логический тип **boolean**, то возвратить из него целочисленное значение нельзя;
* переменная, принимающая возвращаемое методом значение (например, `vol`), также должна быть совместима с возвращаемым типом, указанным для метода.
