JavaRush /Java блог /Random UA /Знайомство з класами: написання власних класів, конструкт...

Знайомство з класами: написання власних класів, конструктори

Стаття з групи Random UA
Вітання! Сьогодні ми поговоримо про класи 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;
}
Це два абсолютно різні конструктори! Тепер виріши кілька завдань на закріплення матеріалу:)
  • Музей старожитностей.
Твоє завдання - спроектувати клас 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) {

    }
}
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ