Перейти до вмісту

Class

Матеріал з K2 ERP Wiki

Приклад, де клас зайвий:

`deposit` — method. const user = await this.userRepository.findById(userId);

id: string;

}

Практична порада: якщо ви постійно передаєте разом ті самі інформаційні дані й функції, можливо, вони просяться в клас. Method — функція, яка належить класу або об’єкту.

</syntaxhighlight>

Типові помилки початківців

error(message: string) {

критично: mutable state не виступає як злом, але його потрібно контролювати через methods і invariants. area() {

Функція `makeSound` не знає, чи отримала Dog, Cat або інший об’єкт.

критично: якщо клас не проєктувався для inheritance, іноді краще явно заборонити наслідування.== Entity Class == Instance або екземпляр — це конкретний об’єкт, створений на основі класу. * Іноді найкраще покращення класу — видалити його й залишити просту функцію. * У C++ class здатна керувати ресурсами напряму через RAII. public User(String name) {

Практична роль: DTO оптимізує не змішувати зовнішній формат API з внутрішньою domain model. Приклад: }

self.name = name
throw new Error("Invalid email address");
  • потрібна одна проста pure function;
  • немає стану;
  • немає invariants;
  • немає lifecycle;
  • це без зусиль одноразова трансформація;
  • class буде мати одну маленьку функцію без сенсу;
  • створюється abstraction “на майбутнє”;
  • module з функціями читається простіше.</syntaxhighlight>

Composition часто формулюють як:

'''Перевага:''' клас дає можливість зібрати пов’язані інформаційні дані й дії разом, щоб код був організованішим і ближчим до реальної моделі задачі. return "Hello, " + name;
!<div style="background:#fdecea; border-left:6px solid #e74c3c; padding:12px; margin:12px 0;">
  • виступає як проста операційна дія;
  • немає складного стану;
  • логіка чиста;
  • потрібне перетворення даних;
  • немає потреби створювати object. User(std::string name) : name(name) {}

Проста різниця: module — це папка або розділ знань, class — це модель конкретної сутності.

Class і Struct

Property — властивість об’єкта. Приклад:

self.balance += amount
move() {

Небезпека: найчастіша помилка — думати, що ООП означає “все має бути класом”. !== Interface і Class ==

Приклад JavaScript:
private id: string,
  • instance variables;
  • methods;
  • modules;
  • mixins;
  • inheritance;
  • metaprogramming;
  • open classes. Проблема виникає, коли domain logic розкидана по services, а domain classes не захищають власні правила.
    Приклад C#:
    Проблеми:
    '''Polymorphism''' або '''поліморфізм''' дає можливість працювати з різними обєктами через спільний інтерфейс або base class. '''критично:''' private  це не без зусиль сховати від очей, а спосіб зберегти invariants класу. Різниця
     def __init__(self, balance):
    

Class у Python

  • читати значення;
  • змінювати значення;
  • виконувати validation;
  • обчислювати значення;
  • приховувати внутрішнє поле. Суть

Практична роль: data class зменшує boilerplate для простих об’єктів даних. ReportExporter

public readonly currency: string
// database query

</syntaxhighlight>

Чи швидко написати tests? def greet(self):

Mutable class дає можливість змінювати стан object після створення.

Field — змінна, яка належить об’єкту або класу. Інакше ієрархія оперативно стає заплутаною. Якщо ім’я вибрано добре, код починає читатися майже як мова задачі. handle() {

  • конфлікти методів;
  • diamond problem;
  • складніша логіка lookup;
  • важче читати код;
  • несподівана поведінка.

</syntaxhighlight>

private String name;

Приклад:

Repository здатна приховувати:

}

const phone = new Product("Phone", 500);

Helper
 }

Module часто групує functions, classes, constants або types. * нечітка назва;
* `any`;
* багато незрозумілих methods;
* немає явної відповідальності;
* важко тестувати;
* важко підтримувати. UserManager:

class Product {
Класи виступає як важливою частиною ООП, але ООП  це не без зусиль створити багато класів. У різних мовах property здатна бути без зусиль field або спеціальним способом доступу до даних через getter/setter. Поняття

class CreateUserDto {
== Method ==
class Dog(Animal):

<syntaxhighlight lang="typescript">

конкурентні переваги:

== Class і Dependency Injection ==

<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
{
</div>
 this.name = name;
public class User {

 constructor(
'''Final class'''  клас, який не можна наслідувати. class EmailAddress {
</div>
Добрий клас:
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

 User.count += 1
UserRepository
'''Проста аналогія:''' class  це форма для печива, object  конкретне печиво, яке з цієї форми зробили.== Single Responsibility Principle ==
 def increment(self):

== Mixin ==

 }

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

* inheritance;
* composition;
* aggregation;
* associations;
* interfaces;
* dependencies;
* visibility;
* multiplicity. Він означає одну зрозумілу відповідальність. '''Getter''' читає значення, '''setter''' змінює значення. InvoiceGenerator

 return `Area: ${this.area()}`;

== Коли Class здатна бути зайвим ==

== Див. так само ==

* PaymentService;
* EmailService;
* ReportService;
* OrderPricingService;
* AuthService;
* NotificationService. У такому випадку краще названий method, як приклад `changeEmail`.
  • давати класам точні назви;
  • тримати одну основну відповідальність;
  • приховувати internal state;
  • робити objects валідними після constructor;
  • не створювати God classes;
  • не будувати глибокі inheritance trees без потреби;
  • надавати маленький public interface;
  • використовувати composition, коли inheritance зайве;
  • писати tests для важливих methods;
  • не змішувати domain logic і infrastructure без потреби;
  • захищати invariants;
  • використовувати immutable objects там, де це доречно;
  • передавати dependencies через constructor;
  • не використовувати static state без потреби.

критично: ООП не означає автоматизовано хороший дизайн. Практична порада: не використовуйте setter, якщо зміна значення має складну бізнес-логіку. * `Order`;

  • `Customer`;
  • `Invoice`;
  • `Payment`;
  • `Shipment`;
  • `Product`;
  • `Subscription`;
  • `Account`;
  • `Booking`. Класи виступає як фундаментальним поняттям ООП і використовуються для моделювання domain entities, services, repositories, controllers, value objects, UI components і багатьох інших частин програм. Controller class часто застосовують, коли потрібно в web frameworks для обробки HTTP-запитів.== Приклад checklist для Class ==
{

Добрий service class має чітку відповідальність. }

Inner class у деяких мовах має спеціальний доступ до зовнішнього instance. * Глибока inheritance tree здатна виглядати красиво на діаграмі, але бути дуже болючою в підтримці. Приклад спрощено:

Практична роль: class diagram оптимізує побачити структуру системи до або під час реалізації.
Class/static method викликається на самому класі. Python підтримує класи, але має більш динамічну модель.
// cannot be subclassed
}

Погано:

}

  • collections;
  • repositories;
  • wrappers;
  • result types;
  • API responses;
  • reusable data structures. У багатьох системах composition дає гнучкіший дизайн. * Data classes і records з’явилися, щоб прибрати boilerplate для простих data containers. Order

Class у TypeScript

Коли варто створювати Class

}

this._name = name;

}

Abstraction або абстракція у класах означає виділення суттєвого й приховування деталей.
String name;

Приклади: критично: multiple inheritance — потужний інструмент, але він потребує дисципліни. @classmethod

Anemic Class

- рахує billing class Circle extends Shape { User + TimestampMixin → User має createdAt і updatedAt behavior

return a + b;

Код, який викликає `send`, не мусить знати всі деталі SMTP, retries, templates або provider API. |-

C++ `class` має private members за замовчуванням, `struct` — public
C# class — reference type, struct — value type
Swift class — reference type, struct — value type

</syntaxhighlight> </syntaxhighlight>

Methods описують поведінку:

Generics корисні для:

constructor(

|- | Class | Шаблон для створення об’єктів |- | Module | Організаційна одиниця коду або namespace |}

Sealed class обмежує, які класи можуть її наслідувати.
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
 }
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
Приклад:
Основні принципи ООП:
 constructor(public value: T) {}
</div>

'''Inheritance''' або '''наслідування''' дає можливість одному класу успадковувати властивості й методи іншого класу. * `Manager`;
* `Helper`;
* `Processor`;
* `Data`;
* `Object`;
* `Common`;
* `Utils`;
* `Thing`;
* `Service2`. {| class="wikitable"

 return this._name;

 public String greet() {

'''Generic class''' — клас, який функціонує з типом як параметром. Це потужно, але потребує обережності. self.value += 1

class UserController {

 def deposit(self, amount):
 if (this.status !== "draft") {
class Counter:
 return "Woof";
<syntaxhighlight lang="typescript">
 // unclear responsibility

 constructor(public readonly value: string) {

 async save(user: User): Promise<void> {

* ім’я користувача;
* ціна товару;
* баланс акаунта;
* статус замовлення;
* дата створення;
* координати персонажа;
* рівень доступу. У деяких мовах виступає як спеціальні конструкції для класів, які переважно зберігають інформаційні дані. Зовнішній код не здатна напряму змінити `balance`, а має використовувати метод `deposit`. У domain-driven design клас здатна представляти поняття предметної області. function addNumbers(a: number, b: number) {
</div>

<syntaxhighlight lang="java">

 console.log(animal.speak());
  • Money;
  • EmailAddress;
  • DateRange;
  • Address;
  • Coordinates;
  • Percentage;
  • Color. return `Hello, ${this.name}`;
  • constructors;
  • destructors;
  • copy/move semantics;
  • operator overloading;
  • templates;
  • inheritance;
  • virtual methods;
  • RAII;
  • access control. Інакше subclass здатна ламати код, який функціонує з base class. Головне правило: клас має бути достатньо маленьким, щоб його можна було зрозуміти, і достатньо змістовним, щоб він не був зайвою обгорткою. private brakes: Brakes
  • helper objects;
  • тісно пов’язаних типів;
  • builders;
  • iterators;
  • implementation details;
  • logical grouping.

C++ classes можуть включати: Поширені modifiers:

execute(a: number, b: number) {

Access Modifiers

addItem(item: string) {

критично: service class швидко перетворити на “мішок логіки”. ) {}

}
  • `dataclass` у Python;
  • `record` у C#;
  • `data class` у Kotlin;
  • `case class` у Scala;
  • `record` у Java;
  • `struct` у Swift. Клас здатна бути зайвим, якщо:
}

User class

Static Members

</div>
Чи залежності передаються явно? }

== Property ==

Приклад TypeScript:

== Constructor ==
Приклад:
! deposit(amount: number) {

<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">

* безпеки;
* стабільності API;
* performance optimization у частині мов;
* заборони неправильного extension;
* immutable value objects. TypeScript додає до JavaScript classes типи й access modifiers. Modifier

 constructor(name) {

}

</div>

* encapsulation;
* abstraction;
* inheritance;
* polymorphism. * Практики software design, domain modeling, SOLID, design patterns, dependency injection і clean architecture. Суть
 this._name = value;

'''критично:''' надмірне використання static methods здатна зробити код менш гнучким для testing і dependency injection.</div>

</div>

* balance не здатна бути меншим за 0;
* email має бути валідним;
* order total не здатна бути відємним;
* start date не здатна бути пізніше end date;
* user role має бути однією з дозволених;
* cart item quantity має бути більшою за 0. Простіше:
'''Помилка:''' більше класів не означає кращу архітектуру. void speak() {
 return Math.PI * this.radius * this.radius;
як приклад, клас `EmailSender` здатна мати метод:
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
Приклад:

У наслідуванні виступає як:
Приклад TypeScript:
<syntaxhighlight lang="typescript">

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

Приклад:

class Car {

* `User`;
* `Order`;
* `Invoice`;
* `PaymentGateway`;
* `EmailSender`;
* `Cart`;
* `Money`;
* `DateRange`;
* `UserRepository`;
* `PasswordResetService`. }
 ) {}
}
}
}

C# активно використовує classes у .NET-екосистемі.<syntaxhighlight lang="typescript">

<syntaxhighlight lang="typescript">

== Sealed Class ==

У цьому прикладі `name` і `email`  fields. Їй критично, що виступає як метод `speak`. як приклад:
</div>
У деяких мовах виступає як і `class`, і `struct`. def greet
Приклад:

}
'''Практична порада:''' nested class корисний, коли тип має сенс тільки в контексті зовнішнього класу. * Найкращий клас часто має менше methods, ніж хочеться додати на старті.
== Service Class ==

}
'''Class''' і '''object'''  повязані, але різні поняття. '''критично:''' SRP не означає один метод на клас. '''критично:''' overriding має зберігати очікуваний контракт методу. }
 console.error(message);
- створює користувачів
Клас `EmailSender` приховує деталі SMTP або external API й дає простий method `send`. Слабкі назви:

Abstract class — клас, який не призначений для створення об’єктів напряму, а задає спільну основу для subclasses. } Практична роль: instance дає можливість одному класу створювати багато незалежних об’єктів із власним станом. name: string;

this.name = name;

TypeScript classes можуть використовувати:

doStuff() {
return f"Hello, {self.name}"
data: any;

Приклади: Приклад:

constructor(

Чи не виступає як це God class?</syntaxhighlight>

BillingService

Практична роль: repository class дає можливість бізнес-логіці не знати деталей database access.

- зберігає в database

}

|- | public | доступний ззовні |- | private | доступний тільки всередині класу |- | protected | доступний у класі й subclasses |- | readonly | значення не можна змінювати після ініціалізації у частині мов |}

}

}
'''Anemic class''' або '''anemic domain model'''  клас, який майже не має поведінки й лише зберігає інформаційні дані. Поняття
</div>
'''Небезпека:''' God class стає центром гравітації хаосу: усе нове інтуїтивно додати туди, поки клас не стає майже нерухомим. Чи не краще використати composition?</div>

== Цікавий факт ==

end

 self.name = name

class Cat {

<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
'''Головна перевага:''' клас оптимізує перетворити розрізнені інформаційні дані й функції на зрозумілу програмну сутність. Тому головне  не без зусиль створювати класи, а моделювати ними реальні поняття й відповідальності системи. Приклад:
 System.out.println("Sound");

== Final Class ==

</div>

* fields;
* properties;
* methods;
* constructor;
* access modifiers;
* static members;
* inheritance rules;
* validation logic;
* business behavior;
* internal state;
* relationships with other classes. Часто краще делегувати її service або domain layer. email: string;
</div>
 if (!value) {

<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">

</div>

<syntaxhighlight lang="javascript">

sealed class PaymentResult
class User {
'''DTO''' або '''Data Transfer Object'''  клас або структура для передачі даних між шарами або системами.

Недоліки і ризики Class

@name = name

Value Object Class

}
  • User;
  • Order;
  • Invoice;
  • Customer;
  • Product;
  • Account;
  • Project.

class Money { критично: різниця між class і struct залежить від мови.== Загальний SEO-опис ==

Практична роль: у C# class часто виступає як основним способом моделювання domain logic, services, entities і application components. class EmailAddress {

Можливі ризики:

  • має зрозумілу назву;
  • захищає invariant;
  • виступає як immutable;
  • має корисну behavior;
  • не робить зайвого.
print("Woof")

Підтримується в деяких мовах, як приклад C++ і Python. class Box<T> {

speak() {
}
count = 0

} UserService

class Cat extends Animal {

this.items.push(item);
describe() {
public price: number

Class і Function

{

} Access modifiers визначають, хто здатна бачити або змінювати members класу. }

if (!value.includes("@")) {

Class Method і Instance Method

public name: string
// does many unrelated things
}

Тут `User` — клас, а `anna` і `oleh` — об’єкти.=== PaymentGateway class ===

Processor

Immutable Class

Практична роль: polymorphism дає можливість писати код, який функціонує з поведінкою, а не з конкретною реалізацією. public string Name { get; }

'''Практична роль:''' generic class дає можливість писати reusable code без втрати type safety. Поняття

'''Практична роль:''' entity class моделює сутність із власною ідентичністю, правилами й історією змін. * `public`;
* `private`;
* `protected`;
* `internal`;
* `readonly`;
* `static`;
* package-private у частині мов. Назва й межі відповідальності мають бути чіткими. конкурентні переваги:
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
class AddNumbers {

Приклади:
Приклад:
<syntaxhighlight lang="typescript">
Клас варто створювати, якщо:
`Vehicle` — base class, `Car` — derived class.</div>
</div>

</div>
'''Головне правило:''' хороший клас має бути зрозумілим за назвою, безпечним у використанні й обмеженим у відповідальності.</div>
== Mutable Class ==
== Abstract Class ==

 response.json(user);

const user = new User("Anna");

 def speak(self):

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
Чи можна пояснити відповідальність одним реченням? }

 return "Hello, " + name;
Ruby виступає як дуже об’єктно-орієнтованою мовою: майже все виступає як об’єктом.</div>

Manager

* повторне використання поведінки;
* гнучкі ієрархії;
* mixin-подібні patterns. oleh = User("Oleh")
 async getUser(request, response) {
PasswordResetService
 process() {
class User {

<syntaxhighlight lang="typescript">
'''Single Responsibility Principle''' або '''SRP''' — принцип, за яким клас має мати одну основну причину для зміни. ! class User:
== Class і Domain Model ==
</div>

== Instance ==

 public User(string name)

* `calculateTotal`;
* `sendEmail`;
* `approveOrder`;
* `withdraw`;
* `render`;
* `validate`;
* `save`;
* `move`;
* `login`. class Cart {
<syntaxhighlight lang="csharp">
`greet` функціонує з конкретним user, а `total_users` — з class-level state. Якщо назва туманна, клас уже важче зрозуміти. - генерує PDF

* validation;
* computed properties;
* controlled access;
* backward compatibility;
* hiding internal representation.<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

== Getter і Setter ==
</div>
class BankAccount {
 end
 name: str
 def __init__(self, name):

'''Практична роль:''' method відповідає на питання: “Що цей об’єкт здатна робити?”
 ) {}
== Class і Object ==
'''Практична роль:''' назва класу — це перша документація.

Mixins часто використовують для: </syntaxhighlight> Приклад Python:

Anonymous class — клас без імені, який створюється прямо на місці використання.

God class — антипатерн, коли один клас знає й робить занадто багато. Якщо потрібен лише контракт, interface часто простіший. Приклад: </syntaxhighlight> Основна ідея: class — це шаблон для створення об’єктів, який об’єднує стан і поведінку в одну зрозумілу модель. як приклад, у реальному світі “автомобіль” — це клас, а конкретна машина біля будинку — об’єкт. Практична роль: mixin дає можливість додавати “домішки” поведінки без створення великої inheritance tree. } </syntaxhighlight>

Anonymous Class

}

Корисно, коли потрібно описати обмежений набір варіантів:

  • створювати class для кожної маленької функції;
  • робити всі fields public;
  • не використовувати constructor для валідного стану;
  • писати God class;
  • називати класи `Manager` і `Helper`;
  • надмірно використовувати inheritance;
  • не розуміти різницю між class і object;
  • плутати static і instance members;
  • зберігати global state у static fields;
  • не тестувати behavior;
  • робити getters/setters для всього без логіки;
  • змішувати database, UI і business logic в одному класі;
  • копіювати Java-style classes у мову, де простіше використати functions.
  • prototypes;
  • `this`;
  • constructor;
  • class fields;
  • private fields;
  • static methods;
  • inheritance через `extends`. PaymentCaptureService
throw new Error("Name is required");

Favor composition over inheritance

JavaScript class syntax зручний для ООП-стилю, але критично пам’ятати про:

JavaScript має class syntax, але під капотом використовує prototype-based inheritance. Ризик
Приклад:
Краще:

Погано:

Constructor зазвичай:

</div>

Якщо обєкт  це конкретна річ у програмі, то клас  це креслення, за яким такі речі створюються.<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
</div>

<syntaxhighlight lang="text">
</div>
'''Практична роль:''' dependency injection дає можливість класу не створювати всі залежності самому, а отримувати їх як готові інструменти.</div>
 }
'''Цікавий момент:''' хороший клас  це не без зусиль коробка для даних, а охоронець правил, за якими ці інформаційні дані можуть змінюватися. * properties;
* methods;
* interfaces;
* inheritance;
* generics;
* access modifiers;
* records;
* partial classes;
* attributes;
* async methods. constructor(name) {
'''Практична порада:''' controller не має містити всю бізнес-логіку. Приклад:
'''Практична роль:''' fields відповідають на питання: Що цей обєкт знає або зберігає?
</div>

Класи можуть створювати проблеми. '''Method overriding'''  коли subclass замінює реалізацію методу з parent class. return this.value.split("@")[1];

`Dog` наслідує `Animal` і змінює поведінку `speak`.

</syntaxhighlight> </syntaxhighlight>

constructor(public readonly value: string) {

- status

Class Diagram

class User

Приклад:

  • utility methods;
  • factory methods;
  • constants;
  • shared counters;
  • configuration у частині сценаріїв;
  • class-level behavior. Mixin — спосіб додати класу поведінку без класичного глибокого inheritance.== Inner Class і Nested Class ==

конкурентні переваги Class

</syntaxhighlight>

Чи public methods справді потрібні? `user` — instance класу `User`. це шаблон, SEO-опис або модель; так само реалізовано які об’єкт зберігає, і поведінка, яку він здатна виконувати виступає ключовою рисою створення об’єктів у програмуванні. Клас здатна захищати invariants через constructor, methods і access modifiers. def __init__(self, name):

  • один простий use case розкиданий по 15 класах;
  • багато classes мають по одному методу;
  • назви стають штучними;
  • важко знайти реальну логіку;
  • абстракції створені “про запас”;
  • code navigation стає болючою.== Object-Oriented Programming ==
if (amount <= 0) {
throw new Error("Amount must be positive");
}
this.balance += amount;
}
getBalance() {
return this.balance;
}

} </syntaxhighlight>

критично: constructor має створювати валідний об’єкт. status: string;

return cls.count
};

 static double(value: number) {

'''Проста аналогія:''' inheritance каже Car виступає як Vehicle, composition каже Car має Engine. }

public class User
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
'''Constructor'''  спеціальний метод, який викликається під час створення обєкта. * Матеріали щодо refactoring, class design, UML class diagrams, composition over inheritance і testing object-oriented code. '''Практична роль:''' TypeScript class дає можливість поєднати JavaScript runtime-модель із compile-time перевіркою типів. private:
 throw new Error("Invalid email");
'''Encapsulation''' або '''інкапсуляція'''  принцип приховування внутрішніх деталей класу й надання контрольованого доступу через methods або properties. Клас `User` зберігає identity, email, name і методи для зміни профілю. std::string name;
@Override

Основні конкурентні переваги класів:

// database write

</syntaxhighlight>

console.log(MathUtils.double(5)); </syntaxhighlight>

}

</syntaxhighlight> class Order {

</syntaxhighlight>

def speak(self):
  • приймає початкові інформаційні дані;
  • ініціалізує fields;
  • перевіряє параметри;
  • встановлює default values;
  • готує object до роботи.
}

</syntaxhighlight> Invariant — правило, яке має залишатися істинним для об’єкта протягом його життя. }

  • side effects;
  • складніше debug;
  • проблеми concurrency;
  • неочікувані зміни state. Поганий ООП-код здатна бути таким самим хаотичним, як і поганий процедурний код.== DTO Class ==
countItems(): number {
 if (amount < 0) {
 throw new Error("Amount cannot be negative");
 }
 }
}

Приклад ідеї: const numberBox = new Box<number>(123);

</syntaxhighlight>

Добрі назви:

Приклад:

Class Design

Class diagram — UML-діаграма, яка показує класи, fields, methods і relationships. критично: клас — це інструмент, а не гарантія хорошого дизайну.

class User

Приклад:

</syntaxhighlight>

Приклад:

total: number;

EmailSender Class design — бізнес-процес визначення, за що клас відповідає, які має fields, methods і relationships. from dataclasses import dataclass

"Hello, #{@name}"
* reusable behavior;
* logging;
* serialization;
* validation;
* permissions;
* UI behavior;
* shared methods. }

class Failed(val reason: String) : PaymentResult()

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

 constructor(private radius: number) {
- email
== Class Naming ==
! Це інтуїтивно, але не варто робити приховану складну роботу без потреби. * types;
* interfaces;
* access modifiers;
* generics;
* abstract classes;
* decorators у частині сценаріїв;
* readonly fields;
* parameter properties. Чи має клас зрозумілу назву? Приклад:
 }
! }

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
'''критично:''' inheritance зручне, але його швидко переоцінити. }

Ознаки:

</div>

User
== Цікаві факти про Class ==
 info(message: string) {

<syntaxhighlight lang="cpp">

* [[Object-Oriented Programming]]
* [[Object]]
* [[Instance]]
* [[Constructor]]
* [[Method]]
* [[Property]]
* [[Field]]
* [[Encapsulation]]
* [[Inheritance]]
* [[Polymorphism]]
* [[Abstraction]]
* [[Interface]]
* [[Abstract Class]]
* [[Composition]]
* [[SOLID]]
* [[Single Responsibility Principle]]
* [[Design Patterns]]
* [[Domain Model]]
* [[Entity]]
* [[Value Object]]
* [[Repository Pattern]]
* [[Dependency Injection]]
* [[UML]]
* [[Class Diagram]]
* [[Java]]
* [[Python]]
* [[JavaScript]]
* [[TypeScript]]
* [[C++]]
* [[C#]]
* [[Ruby]]
* [[Документація]]

'''Головна ідея ООП:''' інформаційні дані й поведінка, які логічно належать одній сутності, можуть жити разом. І не кожен клас має існувати, якщо достатньо простої функції. return a + b;
class User {
<syntaxhighlight lang="typescript">
class User:
 public readonly amount: number,
+ changeEmail()

== Приклади сценаріїв використання ==

* простіше reasoning;
* безпечніше в concurrency;
* менше side effects;
* легше тестувати;
* стабільні value objects. * У GitHub-проєктах різними мовами слово `class` здатна означати дуже різні runtime-моделі.== Приклад хорошого Class ==
 if (!value.includes("@")) {
У C++ class схожий на struct, але за замовчуванням members у class виступає як private.<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

Класи й функції  різні способи організації логіки.<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
 constructor(

<syntaxhighlight lang="java">
 def total_users(cls):
<syntaxhighlight lang="typescript">

<syntaxhighlight lang="python">

@dataclass
const stringBox = new Box<string>("hello");
 System.out.println("Meow");

'''Практична роль:''' value object дає можливість сховати правила й validation у маленькому класі замість розкидати їх по всьому коду. * У Python клас сам виступає як object. '''Цікавий факт:''' у Python класи самі виступає як обєктами, тому їх можна передавати, змінювати й створювати динамічно. markAsPaid() {
 speak() {
У класі зазвичай визначаються інформаційні дані забезпечується через '''Class''' або '''клас'''. Клас `Order` має items, status, total і методи `addItem`, `markAsPaid`, `cancel`. anna = User("Anna")
'''Практична роль:''' anonymous class зручний для короткої одноразової реалізації interface або abstract class. '''критично:''' abstract class корисний, коли виступає як спільна поведінка. Якщо обєкт одразу після створення напівзламаний, клас спроєктований слабко. def __init__(self, name):

Класи використовуються в багатьох мовах:

Приклад:

 async welcomeUser(userId: string) {
};
</div>
=== GameCharacter class ===
Це не завжди погано: DTO або simple data class можуть бути anemic навмисно.<syntaxhighlight lang="text">
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
</div>

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

- id

<syntaxhighlight lang="kotlin">

* overengineering;
* God class;
* class explosion;
* складна inheritance tree;
* tight coupling;
* mutable state bugs;
* hidden side effects;
* boilerplate;
* складне тестування при поганих dependencies;
* надмірні abstractions;
* неправильне моделювання domain;
* плутанина між class і data structure. * Документація мов програмування Java, C#, C++, Python, JavaScript, TypeScript, Ruby, Kotlin і Swift щодо class syntax і object model. як приклад, клас `User` описує, які поля й методи має користувач системи, а конкретний користувач системи Anna або Oleh виступає як обєктом цього класу. }

'''Repository class''' приховує доступ до даних і надає доменний інтерфейс для збереження або пошуку objects. Приклад:
== Invariant ==
! '''Головна думка:''' class  це не без зусиль синтаксис мови. }

Ruby classes підтримують: class Success(val id: String) : PaymentResult()

Generic Class

Чи зрозуміє цей клас інший розробник через місяць? Чи немає зайвого inheritance? Суть

print("Sound")
honk() {
}

Тематичні мітки

Функція добре підходить, коли: class DataManager {

критично: JavaScript classes виглядають схоже на Java або C#, але модель мови має власні особливості. Проста ідея: inheritance дає можливість сказати: “Dog — це особливий вид Animal”.

{

class Animal:

private balance = 0;

через Найлюдяніший факт: клас користувачі можуть програмісту говорити мовою предметної області: не “рядок у таблиці з полями”, а “користувач системи”, “замовлення” або “рахунок”. get name() {

Приклад слабкого Class

return this.items.length;
</div>
class User:
 }

 self.balance = balance
 throw new Error("Only draft orders can be paid");
}

'''Цікавий факт:''' у Ruby можна відкрити існуючий клас і додати до нього методи. '''Static members''' належать класу, а не конкретному object instance. C# classes підтримують:

 public name: string,

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

* має чітку відповідальність;
* має зрозумілу назву;
* приховує внутрішній стан;
* не робить забагато;
* захищає invariants;
* швидко тестується;
* має невеликий public interface;
* не залежить від усього підряд;
* відповідає предметній області.== God Class ==
<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">
}

}

 Name = name;

 }

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
Property здатна:
'''Interface''' описує контракт, а class реалізує поведінку. interface Logger {

class Animal {
== Inheritance vs Composition ==

Class у Ruby

public string Greet()

Це здатна бути корисно для:

constructor(
private emailSender: EmailSender,

Class у C++

  • classes;
  • interfaces;
  • inheritance;
  • access modifiers;
  • constructors;
  • static members;
  • annotations;
  • generics;
  • packages. Погано спроєктований клас здатна зробити код складнішим. }

Практична роль: encapsulation захищає об’єкт від неправильних змін і дає можливість контролювати правила роботи зі станом. критично: у C++ class часто керує не тільки логікою, а й ресурсами: пам’яттю, файлами, locks або handles. Ризики:

  • виступає як стан і поведінка;
  • потрібні invariants;
  • виступає як domain entity;
  • потрібно кілька пов’язаних methods;
  • потрібна polymorphism;
  • потрібна lifecycle-логіка. Це спосіб дати програмній сутності ім’я, стан, правила й поведінку.</syntaxhighlight>
def greet(self):

class MathUtils {

- надсилає email

Чи має клас валідний стан після constructor? Class добре підходить, коли:

InvoiceCalculator Приклад TypeScript: Getters і setters корисні для: </syntaxhighlight>

Repository Class

Клас або interface `PaymentGateway` описує спосіб приймати платежі, а конкретні реалізації працюють із Stripe, PayPal або іншим provider. }

private items: string [] = [];
set name(value) {
}

Краще:

 const user = await userService.findUser(request.params.id);
 private engine: Engine,

Приклад:
DTO здатна використовуватися для:

 }
 console.log("Moving");
 greet() {
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
'''Помилка:''' клас із назвою `Manager` часто приховує те, що команда ще не зрозуміла справжню відповідальність. Суть
 self.name = name

 }

 System.out.println("Running");

<syntaxhighlight lang="text">

</div>
drive() {
}
std::string greet() {

Приклади:

abstract area(): number;

</syntaxhighlight> Entity важлива не тільки своїми полями, а й тим, що це “той самий об’єкт” у часі. greet(): string {

State і Behavior

Entity class — клас, який має identity й життєвий цикл. Service class містить логіку, яка не належить природно одному entity або value object. ) {

Хороші практики Class

Abstraction

Поширені помилки: </syntaxhighlight>

Static members використовують для: </syntaxhighlight> + markAsPaid()

Polymorphism

  • легше тестувати;
  • легше замінювати реалізації;
  • менше hardcoded dependencies;
  • чистіша технічна архітектура;
  • краще separation of concerns. }
void speak() {
public string Name { get; set; }

Назва класу має пояснювати, що він представляє або робить. }

} send(to: string, message: string): Promise<void> </syntaxhighlight> Проста різниця: interface — це обіцянка, class — це виконання цієї обіцянки. Це спосіб моделювати систему через відповідальності, межі й поведінку. Практична роль: checklist оптимізує відрізнити корисний клас від зайвого архітектурного шуму.
== Джерела ==

Чи не виступає як це зайвою обгорткою над однією функцією?

Практична роль: instance method відповідає за поведінку об’єкта, static або class method — за поведінку, пов’язану з класом загалом. Приклад Java:

Composition

error(message: string): void;

public final class Money { Class explosion — ситуація, коли створюється надто багато дрібних або зайвих classes. constructor(name) {

Приклад:

await this.emailSender.send(user.email, "Welcome");
def __init__(self):
  • Матеріали з object-oriented programming щодо classes, objects, inheritance, encapsulation, polymorphism і abstraction. private userRepository: UserRepository

Module і class теж різні. return value * 2;

  • організація коду;
  • моделювання предметної області;
  • поєднання state і behavior;
  • encapsulation;
  • reuse;
  • polymorphism;
  • abstraction;
  • testability у хорошому дизайні;
  • технічна підтримка великих систем;
  • зрозумілі APIs;
  • type safety у типізованих мовах;
  • контроль invariants;
  • можливість inheritance або composition.
     self.value = 0
    

Клас зазвичай містить: Nested class — клас, оголошений всередині іншого класу. return `Hello, ${this.name}`; }

Приклад ідеї:

* виступає як сутність із state і behavior;
* потрібно захистити invariants;
* виступає як domain concept;
* виступає як кілька повязаних methods;
* потрібно створювати багато instances;
* потрібен polymorphism;
* потрібне dependency injection;
* потрібне приховування details;
* виступає як lifecycle або rules;
* проста структура даних уже не справляється. '''Object-Oriented Programming''' або '''ООП'''  стиль програмування, у якому програма моделюється через objects, classes і взаємодію між ними. Коли корисний
<syntaxhighlight lang="typescript">
конкурентні переваги immutable classes:
'''Найлюдяніший факт:''' клас  це спосіб дати частині програми імя, память і поведінку.</div>
</div>
 }

 }

<syntaxhighlight lang="python">

 }

class Dog {
 }
{| class="wikitable"
<syntaxhighlight lang="typescript">
</div>
</div>
 ) {}

 end

! function makeSound(animal: { speak(): string }) {
|-
| Class
| Шаблон або SEO-опис
| `User`
|-
| Object
| Конкретний екземпляр класу
| користувач системи Anna з email `anna@example.com`
|}

 }

 }
'''критично:''' не кожен клас має бути розумним, але domain entity без поведінки часто втрачає сенс ООП.== Висновок ==

У програмуванні ця ідея дуже потужна: розробник здатна думати не про набір випадкових змінних, а про сутності  `User`, `Order`, `Invoice`, `Product`, `Message`, `GameCharacter`. class UserRepository {

 info(message: string): void;

</div>

Добрий domain class містить не тільки поля, а й поведінку, яка має сенс у бізнесі. public:

 id: str

== Class і Record/Data Class ==
'''Підказка:''' хороший class зазвичай можна пояснити одним реченням: Цей клас відповідає за…”
У Java класи виступає як центральним елементом мови. console.log("Beep");
== Class у JavaScript ==
<syntaxhighlight lang="text">
 // unknown behavior
}
<syntaxhighlight lang="typescript">
'''критично:''' не треба робити клас лише тому, що так серйозніше виглядає. '''критично:''' не кожна функція має ставати класом. * state  інформаційні дані обєкта;
* behavior  дії обєкта. Окремо варто відзначити Java, C# і інших мовах. |-
| Inheritance
| виступає як справжній звязок is-a
| Жорстка ієрархія, fragile base class
|-
| Composition
| Обєкт складається з частин або поведінок
| Потрібно більше явного wiring
|}

== Class у C# ==
'''Dependency injection'''  передача залежностей класу ззовні, часто через constructor. - id
Приклад:

class UserService {
}
}

Цей клас:

* `self`;
* dynamic attributes;
* inheritance;
* magic methods;
* dataclasses;
* class variables;
* properties;
* multiple inheritance;
* duck typing. Слабкий клас здатна перетворитися на God class, зайву abstraction або без зусиль контейнер без сенсу. '''Immutable class'''  клас, обєкти якого не змінюються після створення. console.log(message);
{| class="wikitable"
Java активно використовує:
== Class у Java ==
class User {
<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">

 return "Meow";
'''Практична роль:''' immutable class схожий на запечатаний документ: після створення його зміст не змінюється.== Class Explosion ==

Utils

Практична роль: замість передавати email як простий string всюди, клас `EmailAddress` робить правило валідності явним. * У Ruby майже все виступає як object, навіть числа й класи. class ConsoleLogger implements Logger { Сильний клас має чітку відповідальність, зрозумілу назву, захищає свій стан, підтримує invariants і не робить зайвого. String email; Приклад:

}

}

EmailSender class

застосовується для для:

Encapsulation

} Практична роль: sealed class дає можливість моделювати закритий набір станів або результатів без випадкових сторонніх subclasses. У цьому прикладі `items` — state, а `addItem` і `countItems` — behavior. } class Car extends Vehicle {

Inheritance

}

Fields описують стан об’єкта:

  • приймати request;
  • викликати service;
  • повертати response;
  • робити validation;
  • опрацьовувати errors;
  • керувати routing у частині frameworks. Мова

}

} Приклади entities: class Order { як приклад, користувач системи здатна змінити email, але все одно лишається тим самим user за `id`. public void run() {

  • Java;
  • C#;
  • C++;
  • Python;
  • JavaScript;
  • TypeScript;
  • Kotlin;
  • Swift;
  • Ruby;
  • PHP;
  • Scala;
  • Dart;
  • Objective-C;
  • Smalltalk;
  • Groovy.== Class і Module ==

class User:

}
this.status = "paid";
  • сотні або тисячі рядків;
  • багато unrelated methods;
  • багато dependencies;
  • важко тестувати;
  • важко змінювати;
  • клас застосовується для всюди;
  • назва типу `Manager`, `System`, `AppService`;
  • будь-яка зміна ризикована. * SQL;
  • ORM;
  • database driver;
  • cache;
  • mapping rows to objects;
  • persistence details. ! Практична роль: у Java майже весь application code організовується навколо classes.=== Order class ===

class User {

<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

'''Instance method''' викликається на конкретному обєкті.== Method Overriding ==
! Особливості Python classes:

Приклад ідеї:

Клас `GameCharacter` зберігає health, position, inventory і methods для movement або actions. ! return f"Hello, {self.name}"

<div style="background:#fef2f2; border-left:6px solid #ef4444; padding:12px; margin:12px 0;">
'''Value object'''  обєкт, який визначається значенням, а не identity. Не варто переносити правило з C++ напряму в C# або Swift. return $"Hello, {Name}";
'''Практична роль:''' abstraction дає можливість користуватися класом через зрозумілий public interface, не занурюючись у внутрішню реалізацію.

class Vehicle {

async findById(id: string): Promise<User | null> {

</syntaxhighlight>

Field

Поширено в Java та деяких інших мовах. Class — це шаблон для створення об’єктів, який описує їхній стан, поведінку, правила й взаємодію з іншими частинами системи. Підхід

Приклад:

"paid" | "cancelled" = "draft";

Controller здатна: Ризики:

domain(): string {

Composition — підхід, де клас використовує інші об’єкти як частини, замість надмірного наслідування. class User {

  • stateful objects;
  • UI components;
  • game objects;
  • sessions;
  • accumulators;
  • workflows;
  • domain entities.
  • base class — базовий клас;
  • parent class — батьківський клас;
  • superclass — надклас;
  • derived class — похідний клас;
  • child class — дочірній клас;
  • subclass — підклас. * У TypeScript access modifiers частково працюють на compile-time, а JavaScript runtime має власні private fields. Service
}

abstract class Shape {

def initialize(name)

Практична роль: base class задає спільну поведінку, а derived class уточнює або розширює її. Class diagram здатна показувати:

Multiple Inheritance

Слово class у програмуванні означає не “шкільний клас”, а “клас речей” — групу об’єктів із подібними властивостями й поведінкою. Приклад

this.engine.start();
Interface Що об’єкт має вміти
Class Як саме це реалізовано
<syntaxhighlight lang="python">

<syntaxhighlight lang="text">

 this.name = name;

'''Multiple inheritance'''  можливість класу наслідувати кілька parent classes.== Base Class і Derived Class ==

Runnable task = new Runnable() {
Mutable classes корисні для:
class BankAccount:

<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">

<syntaxhighlight lang="java">

* API request;
* API response;
* validation;
* serialization;
* transport між services;
* form data;
* command objects. Клас виступає як одним із ключових понять '''object-oriented programming''' або '''ООП'''. Приклад:

Ознаки:
<syntaxhighlight lang="typescript">
</div>
== Controller Class ==

Приклади:

Клас часто поєднує state і behavior. Class описує конкретний тип об’єкта. super();

Цікавий момент: сильний domain class не без зусиль “має status”, а знає, коли цей status можна змінити.
'''критично:''' property виглядає як інформаційні дані, але іноді за нею здатна стояти логіка. Приклад:
Чи прихований internal state? Іноді це без зусиль складність у костюмі дизайну. Поширено в Kotlin. Рекомендовано:

SEO title: Class — клас у програмуванні, ООП, об’єкти, властивості, методи, наслідування й інкапсуляція

SEO keywords: Class, клас, programming class, object-oriented programming, OOP, object, instance, constructor, method, property, field, inheritance, encapsulation, polymorphism, abstraction, static method, abstract class, interface, composition, class design, software engineering

</noinclude>
 {{SEO
Шаблон для службового SEO-опису сторінки. 

}}


Чи захищені invariants? * Class