Class
Приклад, де клас зайвий:
`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 оптимізує побачити структуру системи до або під час реалізації.// 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 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; }
Назва класу має пояснювати, що він представляє або робить. }
== Джерела ==
Чи не виступає як це зайвою обгорткою над однією функцією?
Практична роль: 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):
Module і class теж різні. return value * 2;
Клас зазвичай містить: 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 описують стан об’єкта:
} } Приклади entities: class Order { як приклад, користувач системи здатна змінити email, але все одно лишається тим самим user за `id`. public void run() {
class User: } this.status = "paid";
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 {
} 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