Пользователь Professor Hans Noodles
Professor Hans Noodles
41 уровень

Знакомство с классами: написание собственных классов, конструкторы

Статья из группы Java Developer
Привет! Сегодня мы поговорим о классах в Java. Классы — это, можно сказать, основа основ программирования на Java. Когда ты станешь программистом, твоей основной задачей будет написание собственных классов с разным функционалом. Знакомство с классами: написание собственных классов, конструкторы - 1Давай разберемся, что же это за штука такая и как она работает :) Как ты уже знаешь, Java — это объектно-ориентированный язык программирования. Все программы состоят из объектов, которые как-то связываются между собой. Класс — это, по сути, шаблон для объекта. Он определяет, как объект будет выглядеть и какими функциями обладать. Каждый объект является объектом какого-то класса. Рассмотрим самый простой пример:

public class Cat {

    String name;
    int age;

}
Допустим, мы пишем программу, и в этой программе нам для чего-то нужны кошки (например, у нас ветеринарная клиника с возможностью онлайн-записи). Мы создали класс Cat, и указали для него две переменные — строку name, и число age. Такие переменные классов называются полями. По сути — это шаблон для всех кошек, которых мы создадим в будущем. У каждой кошки (объекта класса Cat) будет две переменные — имя и возраст.

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Барсик";

        System.out.println("Мы создали кота по имени " + barsik.name + ", его возраст - " + barsik.age);
    }

}
Вот так это работает! Мы создали кота, присвоили ему имя и возраст и вывели все это в консоль. Ничего сложного :) Классы чаще всего описывают предметы и явления окружающего мира. Кошка, стол, человек, молния, страница книги, колесо — все это в твоей программе будет создаваться с помощью отдельных классов. Теперь давай обратим внимание на переменные, которые мы создали в классе Cat. Они называются полями, или переменными экземпляров. В названии, собственно, раскрыта вся их суть. Эти переменные будут у каждого экземпляра (объекта) класса Cat. У каждого кота, которого мы создадим, будет своя переменная name и своя переменная age. Логично, в общем-то: с настоящими котами все так и есть :) Кроме переменных экземпляров существуют и другие — переменные классов, или статические. Дополним наш пример:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Барсик";
        count++;

        Cat vasia = new Cat();
        vasia.age = 5;
        vasia.name = "Вася";
        count++;

        System.out.println("Мы создали кота по имени " + barsik.name + ", его возраст - " + barsik.age);
        System.out.println("Мы создали кота по имени " + vasia.name + ", его возраст - " + vasia.age);

        System.out.println("Общее количество котов = " + count);
    }
}
Вывод в консоль:

Мы создали кота по имени Барсик, его возраст - 3
Мы создали кота по имени Вася, его возраст - 5
Общее количество котов = 2
Теперь у нас в классе появилась новая переменная — count (количество). Она отвечает за подсчет созданных котов. Каждый раз, когда в методе main мы создаем кота, мы увеличиваем эту переменную на 1. Эта переменная обозначена ключевым словом static. Это значит, что она принадлежит классу, а не конкретному объекту класса. Что, конечно, логично: если имя у каждого кота должно быть свое, то счетчик котов нам нужен один на всех. Именно этого позволяет добиться слово static — переменная count одна для всех котов. Обрати внимание: когда мы выводим ее в консоль, мы не пишем barsik.count или vasia.count. Она не принадлежит ни Барсику, ни Васе — она принадлежит всему классу Cat. Поэтому — просто count. Можно также написать Cat.count — это тоже будет правильно. С выводом в консоль переменной name у нас бы такое не прошло:

public class Cat {

    String name;
    int age;

    static int count = 0;

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Барсик";
        count++;

        System.out.println("Мы создали кота по имени " + name + ", его возраст - " + barsik.age);

        System.out.println("Общее количество котов = " + count);
    }
}
Ошибка! name у каждого кота свое. В этом месте компилятор сбивается с толку. "Вывести в консоль имя? А чье имя-то? :/"

Методы

Кроме переменных, у каждого класса есть методы. О них мы поговорим в отдельной лекции более подробно, но общие моменты довольно просты. Методы — это функционал твоего класса; то, что объекты этого класса умеют делать. С одним из методов ты уже знаком — это метод main(). Но метод main, как ты помнишь, является статическим — то есть он принадлежит всему классу (логика такая же, как с переменными). А обычные, нестатические методы, можно вызывать только на конкретных объектах, которые мы создали. Например, если мы хотим написать класс для кошки, нам надо понять, какими функциями кошка должна обладать в нашей программе. Исходя из этого, напишем для нее пару методов:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Мяу!");
    }

    public void jump() {
        System.out.println("Прыг-скок!");
    }

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Барсик";

        barsik.sayMeow();
        barsik.jump();

    }
}
Ну вот, теперь наш класс гораздо больше похож на описание настоящей кошки! У нас теперь не просто кот Барсик с именем и возрастом. Он еще умеет мяукать и прыгать! Какой же кот без такого "функционала" :) Берем конкретный объект — barsik, и вызываем у него методы sayMeow() и jump(). Смотрим в консоль:

Мяу!
Прыг-скок!
Настойщий кот! :)

Создание собственных классов. Абстракция

В будущем тебе придется писать собственные классы. На что нужно обратить внимание при их написании? Если мы говорим о переменных, тебе нужно пользоваться такой вещью как абстракция. Абстракция — один из четырех основных принципов объектно-ориентированного программирования. Он подразумевает выделение главных, наиболее значимых характеристик предмета, и наоборот — отбрасывание второстепенных, незначительных. Например, мы создаем картотеку работников компании. Для создания объектов "работник" мы написали класс Employee. Какие характеристики важны для описания работника в картотеке компании? ФИО, дата рождения, номер социального страхования, ИНН. Но вряд ли в карточке работника компании нам нужны его рост, цвет глаз и волос. Компании эта информация ни к чему. Поэтому для класса Employee мы зададим переменные String name, int age, int socialInsuranceNumber и int taxNumber, а от лишней для нас информации (типа цвета глаз) откажемся, абстрагируемся. А вот если мы создаем картотеку фотомоделей для модельного агентства, ситуация резко меняется. Для описания фотомодели нам как раз очень важны рост, цвет глаз и цвет волос, а вот номер ИНН для нее нам абсолютно не важен. Поэтому в классе Model нам нужно создать переменные int height, String hair, String eyes. Вот так и работает абстракция, все просто! :)

Конструкторы

Давай вернемся к нашему примеру с кошками.

public class Cat {

    String name;
    int age;

    public static void main(String[] args) {
        Cat barsik = new Cat();

        System.out.println("Тут в программе в течение 2-х часов что-то происходит...");

        barsik.age = 3;
        barsik.name = "Барсик";

    }
}
Посмотри на этот код и попробуй догадаться, что с нашей программой не так. На протяжении двух часов в нашей программе существовал кот без имени и возраста! Конечно, это в корне неверно. В базе данных ветеринарной клиники не должно быть котов без информации о них. Сейчас мы отдаем это на откуп программиста. Не забудет он указать имя и возраст — все будет ок. Забудет — в базе будет ошибка, неизвестные коты. Как нам решить эту проблему? Надо каким-то образом запретить создавать котов без имени и возраста. Здесь нам на помощь приходят функции-конструкторы. Приведем пример:

public class Cat {

    String name;
    int age;

    //конструктор для класса Cat
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat barsik = new Cat("Barsik", 5);
    }
}
Конструктор — это, по сути, шаблон для объектов класса. В данном случае мы указывем, что для каждого объекта cat должны быть указаны два аргумента — строка и число. Если мы теперь попытаемся создать безымянного кота — у нас это не получится.

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat barsik = new Cat(); //ошибка!
    }
}
Теперь, когда в классе есть конструктор, компилятор Java знает, как должны выглядеть объекты, и не позволяет создавать объекты без указанных в нем аргументов. Теперь давай разберемся с ключевым словом this, которое ты видишь внутри конструктора. С ним тоже все просто. "this" по-английски — "этот, этого". То есть это слово указывает на конкретный предмет. Код в конструкторе

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}
можно перевести почти дословно: "name для этого кота (которого мы создаем) = аргументу name, который указан в конструкторе. age для этого кота (которого мы создаем) = аргументу age, который указан в конструкторе." После срабатывания конструктора можешь проверить, что нашему коту присвоились все нужные значения:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat barsik = new Cat("Барсик", 5);
        System.out.println(barsik.name);
        System.out.println(barsik.age);
    }
}
Вывод в консоль:

Барсик
5
Когда конструктор отработал:

Cat barsik = new Cat("Барсик", 5);
Внутри него по факту произошло следующее:

this.name = "Барсик";
this.age = 5;
И объекту barsik (он и является this) присвоились значения из аргументов конструктора. На самом деле, если не указать в классе конструкторы у него все равно будет срабатывать конструктор! Но как такое возможно? О_О Дело в том, что в Java у всех классов есть так называемый конструктор по умолчанию. У него нет никаких аргументов, но он срабатывает каждый раз при создании любого объекта любого класса.

public class Cat {

    public static void main(String[] args) {

        Cat barsik = new Cat(); //вот здесь сработал конструктор по умолчанию
    }
}
На первый взгляд это не заметно. Ну создали объект и создали, где тут работа конструктора? Чтобы это увидеть, давай прямо руками напишем для класса Cat пустой конструктор, а внутри него выведем какую-нибудь фразу в консоль. Если она выведется, значит конструктор отработал.

public class Cat {

    public Cat() {
        System.out.println("Создали кота!");
    }

    public static void main(String[] args) {

        Cat barsik = new Cat(); //вот здесь сработал конструктор по умолчанию
    }
}
Вывод в консоль:

Создали кота!
Вот и подтверждение. Конструктор по умолчанию всегда незримо присутствует в твоих классах. Но тебе нужно знать еще одну его особенность. Дефолтный конструктор исчезает из класса, когда ты создаешь какой-то конструктор с аргументами. Доказательство этого, на самом деле, мы уже видели выше. Вот в этом коде:

public class Cat {

    String name;
    int age;

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat barsik = new Cat(); //ошибка!
    }
}
Мы не смогли создать кота без имени и возраста, потому что определили конструктор для Cat: строка + число. Дефолтный конструктор сразу после этого исчез из класса. Поэтому обязательно запомни: если тебе в твоем классе нужно несколько конструкторов, включая пустой, его нужно создать отдельно. Например, наша ветеринарная клиника хочет делать добрые дела и помогать бездомным котикам, чьих имен и возраста мы не знаем. Тогда наш код должен выглядеть так:

public class Cat {

    String name;
    int age;

    //для домашних котов
    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //для уличных котов
    public Cat() {
    }

    public static void main(String[] args) {
        
        Cat barsik = new Cat("Barsik", 5);
        Cat streetCat = new Cat();
    }
}
Теперь, когда мы явно указали конструктор по умолчанию, мы можем создавать котов обоих типов. В конструкторе можно присваивать значения и явно, а не только брать их из аргументов. Например, мы можем записывать всех уличных котов в базу данных под именем "Уличный кот номер..." :

public class Cat {

    String name;
    int age;

    static int count = 0;

    public Cat() {
        count++;
        this.name = "Уличный кот номер " + count;
    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat streetCat1 = new Cat();
        Cat streetCat2 = new Cat();
        System.out.println(streetCat1.name);
        System.out.println(streetCat2.name);
    }
}
У нас есть переменная count, которая является счетчиком уличных котов. Каждый раз при выполнении конструктора по умолчанию мы увеличиваем ее на 1 и присваем этот номер в качестве имени кота. Для конструктора очень важен порядок следования аргументов. Поменяем в нашем конструкторе аргументы имени и возраста местами.

public class Cat {

    String name;
    int age;

    public Cat(int age, String name) {
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

        Cat barsik = new Cat("Барсик", 10); //ошибка!
    }
}
Ошибка! Конструктор четко описывает: при создании объекта Cat ему должны быть переданы число и строка, именно в таком порядке. Поэтому наш код не срабатывает. Обязательно запомни это и учитывай при создании своих собственных классов:

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}

public Cat(int age, String name) {
    this.age = age;
    this.name = name;
}
Это два абсолютно разных конструктора! Знакомство с классами: написание собственных классов, конструкторы - 2Теперь реши несколько задач на закрепление материала :)
  • Музей древностей.
Твоя задача — спроектировать класс Artifact. Артефакты, которые хранятся в музее, бывают трех видов. Первый — о которых неизвестно ничего, кроме порядкового номера, присвоенному музеем (например: 212121). Второй — о которых известен порядковый номер и культура, которой он был создан (например: 212121, "Ацтеки"). Третий вид — о которых известен порядковый номер, культура, которой он был создан, и точный век его создания (например: 212121, "Ацтеки", 12). Создай класс Artifact, описывающий хранящиеся в музее древности, и напиши необходимое количество конструкторов для него. В методе main() создай по одному артефакту каждого вида.

public class Artifact {

    public static void main(String[] args) {
    }
}
  • Сайт знакомств
Вы создаете базу данных пользователей для сайта знакомств. Да вот беда — вы подзабыли в каком порядке их нужно указывать, а технического задания под рукой нет. Спроектируйте класс User, у которого будут поля — имя (String) возраст (short) и рост (int). Создайте для него необходимое количество конструкторов, чтобы имя, возраст и рост можно было указывать в любом порядке.

public class User {

    String name;
    short age;
    int height;

    public static void main(String[] args) {
        
    }
}
Комментарии (2141)
Чтобы просмотреть все комментарии или оставить свой,
перейдите в полную версию
Павел Котов 2 уровень, Новосибирск
14 мая 2021
У меня выдает ошибки, ругается как я понял на то что не понимает что тут int а что short Как починить кто знает?

package com.company;

public class User {
    String name;
    short age;
    int height;

    public static void main(String argc[]){
        User masha = new User("Masha", 162, 21);
        User tanya = new User(154, "Tanya", 33);
        User sveta = new User(160, 26, "Sveta");
        User liza = new User(30, 164, "Liza");
        User zina = new User(29, "Zina", 173);
        System.out.println(masha.name);
        System.out.println(sveta.name);
        System.out.println(tanya.name);
        System.out.println(liza.name);
        System.out.println(zina.name);
    }
    public User(String name, short age, int height){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public User(short age, String name, int height){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public User(int height, short age, String name){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public User(String name, int height, short age){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public User(short age, int height, String name){
        this.name = name;
        this.age = age;
        this.height = height;
    }
    public User(int height, String name, short age){
        this.name = name;
        this.age = age;
        this.height = height;
    }
}
Дмитрий Б.Г. 4 уровень
13 мая 2021
Задача №1

public class Artifact {
    int number, century;
    String culture;

    public static void main(String[] args){
        Artifact knife = new Artifact(123);
        Artifact mirror = new Artifact(124, "Aztec");
        Artifact sceptre = new Artifact(125, "Aztec", 12);
    }
    
    public Artifact(int number){
        this.number = number;
    }
    public Artifact(int number, String culture){
        this.number = number;
        this.culture = culture;
    }
    public Artifact(int number, String culture, int century){
        this.number = number;
        this.culture = culture;
        this.century = century;
    }
}
Зухра 11 уровень, Москва
28 апреля 2021
public class Artifact{ int number; String culture; int age; public Artifact(int number) { this.number = number; } public Artifact(int number, String culture) { this.number = number; this.culture = culture; } public Artifact(int number, String culture, int age) { this.number = number; this.culture = culture; this.age = age; } public static void main(String [] args) { Artifact first_art = new Artifact(212121); Artifact second_art = new Artifact(212121, "Ацтеки"); Artifact thirth_art = new Artifact(212121, "Ацтеки", 12); System.out.println(first_art.number); System.out.println(second_art.number + " " + second_art.culture); System.out.println(thirth_art.number + " " + thirth_art.culture + " " + thirth_art.age); } }
AlekDyai 3 уровень, Москва
26 апреля 2021

public class Artifact {

    private int id;
    private String culture;
    private int data;
    static int count = 0;

    public Artifact(int id) // 1 параметр
    {
        count++;
        this.id = id;
    }

    public Artifact(int id, String culture) // 2 параметра
    {
        count++;
        this.id = id;
        this.culture = culture;
    }
    public Artifact(int id, String culture, int data)  // 3 параметра
    {
        count++;
        this.id = id;
        this.culture = culture;
        this.data = data;
    }

    public static void main(String[] args) {
        Artifact artifact = new Artifact(10);
        Artifact artifact1 = new Artifact(11, "Апачи");
        Artifact artifact2 = new Artifact(12, "Команчи", 14);


        System.out.println("ID Артефакта " + artifact.id);
        System.out.println("ID Артефакта " + artifact1.id + " Культура " + artifact2.culture);
        System.out.println("ID Артефакта " + artifact1.id + " Культура " + artifact2.culture + " Век его создания " + artifact2.data);
        System.out.println("Количество Артефактов " +count);

    }
}
Михайло Романишин 14 уровень, Львов
23 апреля 2021
Интересно сделать с добавлением номера Артефакта. Чтоб заработало нужно добавить "static" к переменной, которая считает количество артефактов.
public class Artifact {
    private String name;
    private int numberId;
    private String cult;
    private short age;
    private static int count;

    public Artifact (String name, int numberId) {
        this.numberId = (numberId > 0) ? numberId : 0;
        this.count = ++count;

        System.out.print(count + ". ");
        System.out.println(name);
        System.out.println("Artefact ID Number: " + numberId);
        System.out.println();
    }

    public Artifact (String name, int numberId, String cult) {
        this.numberId = (numberId > 0) ? numberId : 0;
        this.cult = cult;
        this.count = ++count;

        System.out.print(count + ". ");
        System.out.println(name);
        System.out.println("Artefact ID Number: " + numberId);
        System.out.println("Culture: " + cult);
        System.out.println();
    }

    public Artifact (String name, int numberId, String cult, short age) {
        this.numberId = (numberId > 0) ? numberId : 0;
        this.cult = cult;
        this.age = ((age > 0) && (age < 21)) ? age : null;
        this.count = ++count;

        System.out.print(count + ". ");
        System.out.println(name);
        System.out.println("Artefact ID Number: " + numberId);
        System.out.println("Culture: " + cult);
        System.out.println("Age: " + age + " B.C.");
        System.out.println();
    }

    public static void main(String[] args) {
        Artifact diadem = new Artifact("Diadem", 212121);
        Artifact knife = new Artifact("Knife", 212122, "Aztecs");
        Artifact arrow = new Artifact("Arrow", 212123, "Unknown", (short) 2);
    }
}


Алексей 4 уровень, Москва
15 апреля 2021
не сразу получилось счетчик прикрутить, но вроде заработало и сразу стало понятно) надеюсь кому-нибудь будет полезно.

public class Artifact {
    static int count = 0;
    String name;
    int age;
    int num;

    public Artifact() {
        count++;
        this.num = count;
    }

    public Artifact(int num, String name) {
        count++;
        this.num = count;
        this.name = name;
    }

    public Artifact(int num, String name, int age) {
        count++;
        this.num = count;
        this.name = name;
        this.age = age;
    }

    public static void main(String[] args) {

    Artifact first = new Artifact();
    Artifact second = new Artifact(0,"Acteki");
    Artifact third = new Artifact(0,"Acteki", 12);
        System.out.println(first.num);
        System.out.println(second.num + ", " + second.name);
        System.out.println(third.num + ", " + third.name + ", " + third.age);
    }
}
Юрий 3 уровень, Самара
14 апреля 2021
public class Artifact{ int number, vek; String culture; public Artifact(int number){ this.number = number; } public Artifact(int number, String culture){ this.number = number; this.culture = culture; } public Artifact(int number, String culture, int vek){ this.number = number; this.culture = culture; this.vek = vek; } public static void main(String[] args) { Artifact artifact1 = new Artifact(1); Artifact artifact2 = new Artifact(2, "Мезозой"); Artifact artifact3 = new Artifact (3, "Палеолит", 3); System.out.println("Создали новый артефакт # " + artifact1.number); System.out.println("Создали новый артефакт # " + artifact2.number + " культура: " + artifact2.culture); System.out.println("Создали новый артефакт # " + artifact3.number + " культура: " + artifact3.culture + " век: " + artifact3.vek); } }
Java_Vnyk 10 уровень, Киев
4 апреля 2021
class Artifact { int id; String culture; int century; static int count = 0; public Artifact(int id){ count++; this.id = id; } public Artifact(int id, String culture){ count++; this.id = id; this.culture = culture; } public Artifact(int id, String culture, int century){ count++; this.id = id; this.culture = culture; this.century = century; } public static void main (String[]args){ Artifact art1 = new Artifact(123); Artifact art2 = new Artifact(56, "Черняховская"); Artifact art3 = new Artifact(267, "Киевская Русь", 12); System.out.println("Артифакт под номером: " + art1.id + "."); System.out.println("Артифакт под номером: " + art2.id + ". Культура: " + art2.culture +"."); System.out.println("Артифакт под номером: " + art3.id + ". Культура: " + art3.culture + ". Век: " + art3.century); System.out.println("Общее количество Артифактов в базе: " + count); } } Консоль: Артифакт под номером: 123. Артифакт под номером: 56. Культура: Черняховская. Артифакт под номером: 267. Культура: Киевская Русь. Век: 12 Общее количество Артифактов в базе: 3
Chernenko Nikita 28 уровень, Белгород Белгород
30 марта 2021
public class Main { private int serialnumber; private String culture; private char century; public Main (int serialnumber) { this.serialnumber = serialnumber; } public Main (int serialnumber, String culture) { this.serialnumber = serialnumber; this.culture = culture; } public Main (int serialnumber, String culture, char century) { this.serialnumber = serialnumber; this.culture = culture; this.century = century; } public static void main(String[] args) { Main archive = new Main(518); Main archive2 = new Main(180, "Татары"); Main archive3 = new Main(56, "Неизвестная расса", 'V' ); System.out.println("Порядковый номер в архиве \"Монголы\": "+archive.serialnumber); System.out.println("Порядковый номер и культура: "+ archive2.serialnumber+ " " +"\""+ archive2.culture +"\""); System.out.println("Порядковый номер,культура,век: "+archive3.serialnumber +" " + "" + "\"" + archive2.culture + "\"" + " "+archive3.century + " век"); } }
Александр 6 уровень, Симферополь
29 марта 2021
закоментил я его сам чтоб код работал