Skip to content
IRC-CodingIRC-Coding
OOP понятияатрибутысообщениявызов методовpersistenceinterfacesAPI

Основные понятия OOP: атрибуты, сообщения, методы

Изучите ключевые концепции OOP: атрибуты, вызовы методов, persistence, interfaces с практическими примерами.

S

schutzgeist

10 min read
Основные понятия OOP: атрибуты, сообщения, методы

Концепции ООП: атрибуты, сообщения, вызовы методов, персистентность и интерфейсы

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

Кратко

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

Определение

Объектно-ориентированное программирование (ООП) использует специальную терминологию для описания концепций и структур.

Атрибут (Attribute/Field/Property)

Атрибут - это свойство или состояние объекта. Он хранит данные, которыми обладает объект.

Характеристики:

  • Тип данных: определяет, какого типа данные хранятся (String, int, boolean и т.д.)
  • Видимость: public, private, protected, package
  • Значение: текущее состояние свойства
  • Время жизни: существует столько же, сколько сам объект

Сообщение (Message/Method Call)

Сообщение - это взаимодействие между объектами. Оно заставляет объект выполнить определённое действие.

Составные части:

  • Получатель: объект, который получает сообщение
  • Селектор: имя вызываемого метода
  • Аргументы: параметры метода
  • Возвращаемое значение: результат операции

Персистентность (Persistence)

Персистентность - это сохранение данных за пределами времени выполнения программы.

Способы реализации:

  • Файловая система: сохранение в файлы
  • Базы данных: реляционные или NoSQL
  • Облачные хранилища: внешние сервисы хранения
  • In-Memory: временное хранение

Интерфейс (Interface/API)

Интерфейс определяет контракт между компонентами и описывает доступные операции.

Типы интерфейсов:

  • API программирования: сигнатуры методов
  • Web-API: HTTP-endpoints
  • Пользовательский интерфейс: компоненты GUI
  • Аппаратные интерфейсы: драйверы устройств

Ключевые моменты

  • Атрибуты: свойства и данные объектов с контролем видимости
  • Сообщения: взаимодействие объектов через вызовы методов
  • Вызов методов: выполнение операций над объектами
  • Персистентность: долгосрочное сохранение данных
  • Интерфейсы: контракты между компонентами, определённые API
  • Инкапсуляция: объединение данных и методов в единое целое
  • Абстракция: упрощение через скрытие сложности
  • Полиморфизм: множественные формы одного интерфейса

Основные элементы

  1. Атрибуты: свойства данных объектов
  2. Сообщения: взаимодействие между объектами
  3. Методы: реализация поведения
  4. Персистентность: долгосрочное хранение данных
  5. Интерфейсы: определённые контракты
  6. Инкапсуляция: объединение данных и методов
  7. Абстракция: снижение сложности
  8. Полиморфизм: несколько форм интерфейса

Практические примеры

1. Атрибуты в разных языках

// Java-атрибуты
public class Auto {
    // Атрибуты экземпляра (для каждого объекта свои)
    private String marke;           // Приватное свойство
    protected int baujahr;          // Защищённое свойство
    public double preis;            // Открытое свойство
    
    // Атрибут класса (общий для всех объектов)
    private static int anzahlAutos = 0;
    
    // Константа
    public static final int MAX_GESCHWINDIGKEIT = 250;
    
    // Конструктор для инициализации
    public Auto(String marke, int baujahr, double preis) {
        this.marke = marke;
        this.baujahr = baujahr;
        this.preis = preis;
        Auto.anzahlAutos++; // Увеличиваем счётчик
    }
    
    // Getter и setter для инкапсулированных атрибутов
    public String getMarke() {
        return marke;
    }
    
    public void setMarke(String marke) {
        this.marke = marke;
    }
    
    public static int getAnzahlAutos() {
        return anzahlAutos;
    }
}
// C#-атрибуты
public class Mitarbeiter
{
    // Автоматические свойства (современный синтаксис)
    public string Name { get; set; }
    public int Alter { get; private set; }  // Только чтение снаружи
    
    // Полное свойство с валидацией
    private double gehalt;
    public double Gehalt
    {
        get { return gehalt; }
        set
        {
            if (value >= 0)
                gehalt = value;
            else
                throw new ArgumentException("Gehalt kann nicht negativ sein");
        }
    }
    
    // Статическое свойство
    public static string Firma { get; set; } = "TechCorp";
    
    // Константа
    public const decimal MINDESTGEHALT = 2000m;
    
    public Mitarbeiter(string name, int alter, double gehalt)
    {
        Name = name;
        Alter = alter;
        Gehalt = gehalt;
    }
}
# Python-атрибуты
class Person:
    # Атрибут класса
    anzahl_personen = 0
    
    def __init__(self, name, alter):
        # Атрибуты экземпляра
        self.name = name          # Открытый
        self._alter = alter       # Защищённый (по соглашению)
        self.__geheim = "data"    # Приватный (Name Mangling)
        
        Person.anzahl_personen += 1
    
    # Property для инкапсулированного доступа
    @property
    def alter(self):
        return self._alter
    
    @alter.setter
    def alter(self, wert):
        if wert >= 0:
            self._alter = wert
        else:
            raise ValueError("Alter kann nicht negativ sein")
    
    # Статический метод
    @staticmethod
    def get_anzahl_personen():
        return Person.anzahl_personen

2. Сообщения и вызовы методов

// Сообщения между объектами
public class Bankkonto {
    private double kontostand;
    private String kontonummer;
    
    public Bankkonto(String kontonummer, double startbetrag) {
        this.kontonummer = kontonummer;
        this.kontostand = startbetrag;
    }
    
    // Метод для получения сообщений
    public void einzahlen(double betrag) {
        if (betrag > 0) {
            this.kontostand += betrag;
            System.out.println("Einzahlung: " + betrag + "€, neuer Kontostand: " + kontostand + "€");
        }
    }
    
    public boolean abheben(double betrag) {
        if (betrag > 0 && kontostand >= betrag) {
            kontostand -= betrag;
            System.out.println("Abhebung: " + betrag + "€, neuer Kontostand: " + kontostand + "€");
            return true;
        }
        return false;
    }
    
    public double getKontostand() {
        return kontostand;
    }
    
    public String getKontonummer() {
        return kontonummer;
    }
}

// Клиент отправляет сообщения на счёт
public class Kunde {
    private String name;
    private Bankkonto konto;
    
    public Kunde(String name, Bankkonto konto) {
        this.name = name;
        this.konto = konto;
    }
    
    // Клиент отправляет сообщения своему счёту
    public void geldEinzahlen(double betrag) {
        System.out.println(name + " will " + betrag + "€ einzahlen");
        konto.einzahlen(betrag);  // Отправляем сообщение
    }
    
    public boolean geldAbheben(double betrag) {
        System.out.println(name + " will " + betrag + "€ abheben");
        return konto.abheben(betrag);  // Отправляем сообщение
    }
    
    public void kontostandPruefen() {
        double stand = konto.getKontostand();  // Отправляем сообщение
        System.out.println(name + "'s Kontostand: " + stand + "€");
    }
}

// Использование сообщений
public class BankingDemo {
    public static void main(String[] args) {
        Bankkonto konto = new Bankkonto("DE123456789", 1000.0);
        Kunde kunde = new Kunde("Max Mustermann", konto);
        
        // Цепь сообщений
        kunde.geldEinzahlen(500.0);
        kunde.kontostandPruefen();
        
        if (kunde.geldAbheben(200.0)) {
            System.out.println("Abhebung erfolgreich");
        }
        
        kunde.kontostandPruefen();
    }
}

3. Реализация персистентности

// Сериализация для сохранения данных в файл
import java.io.*;
import java.util.*;

public class PersistenzDemo {
    
    // Сериализуемый класс
    static class Produkt implements Serializable {
        private static final long serialVersionUID = 1L;
        
        private String id;
        private String name;
        private double preis;
        private transient Date lastModified; // transient = не сериализуется
        
        public Produkt(String id, String name, double preis) {
            this.id = id;
            this.name = name;
            this.preis = preis;
            this.lastModified = new Date();
        }
        
        // Геттеры и toString
        public String getId() { return id; }
        public String getName() { return name; }
        public double getPreis() { return preis; }
        
        @Override
        public String toString() {
            return String.format("Produkt[id=%s, name=%s, preis=%.2f]", id, name, preis);
        }
    }
    
    // Менеджер персистентности
    static class PersistenzManager {
        private String dateiname;
        
        public PersistenzManager(String dateiname) {
            this.dateiname = dateiname;
        }
        
        // Сохранение объектов
        public void speichereProdukte(List<Produkt> produkte) throws IOException {
            try (ObjectOutputStream oos = new ObjectOutputStream(
                    new FileOutputStream(dateiname))) {
                oos.writeObject(produkte);
                System.out.println("Produkte gespeichert in " + dateiname);
            }
        }
        
        // Загрузка объектов
        @SuppressWarnings("unchecked")
        public List<Produkt> ladeProdukte() throws IOException, ClassNotFoundException {
            try (ObjectInputStream ois = new ObjectInputStream(
                    new FileInputStream(dateiname))) {
                List<Produkt> produkte = (List<Produkt>) ois.readObject();
                System.out.println("Produkte geladen aus " + dateiname);
                return produkte;
            }
        }
    }
    
    // JSON-персистентность (ручная реализация)
    static class JsonPersistenz {
        public static void speichereAlsJson(List<Produkt> produkte, String dateiname) throws IOException {
            try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(dateiname))) {
                writer.write("[\n");
                for (int i = 0; i < produkte.size(); i++) {
                    Produkt p = produkte.get(i);
                    writer.write(String.format(
                        "  {\"id\": \"%s\", \"name\": \"%s\", \"preis\": %.2f}",
                        p.getId(), p.getName(), p.getPreis()
                    ));
                    if (i < produkte.size() - 1) {
                        writer.write(",\n");
                    }
                }
                writer.write("\n]");
            }
            System.out.println("Produkte als JSON gespeichert");
        }
    }
    
    public static void main(String[] args) {
        List<Produkt> produkte = Arrays.asList(
            new Produkt("P001", "Laptop", 999.99),
            new Produkt("P002", "Maus", 29.99),
            new Produkt("P003", "Tastatur", 79.99)
        );
        
        PersistenzManager manager = new PersistenzManager("produkte.ser");
        
        try {
            // Сериализация
            manager.speichereProdukte(produkte);
            
            // Десериализация
            List<Produkt> geladeneProdukte = manager.ladeProdukte();
            geladeneProdukte.forEach(System.out::println);
            
            // JSON-персистентность
            JsonPersistenz.speichereAlsJson(produkte, "produkte.json");
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

4. Интерфейсы и API

// Интерфейс программирования
interface DatenbankSchnittstelle {
    // Абстрактные методы (без реализации)
    void verbinden() throws DatenbankException;
    void trennen();
    boolean istVerbunden();
    
    // Методы запросов
    List<Map<String, Object>> abfragen(String sql) throws DatenbankException;
    int ausfuehren(String sql) throws DatenbankException;
    
    // Default-методы (с Java 8)
    default void verbindenMitTimeout(int timeout) throws DatenbankException {
        verbinden(); // Стандартная реализация
    }
}

// Пользовательский класс исключения
class DatenbankException extends Exception {
    public DatenbankException(String nachricht) {
        super(nachricht);
    }
    
    public DatenbankException(String nachricht, Throwable ursache) {
        super(nachricht, ursache);
    }
}

// Конкретная реализация
class MySQLDatenbank implements DatenbankSchnittstelle {
    private boolean verbunden = false;
    private String verbindungsString;
    
    public MySQLDatenbank(String verbindungsString) {
        this.verbindungsString = verbindungsString;
    }
    
    @Override
    public void verbinden() throws DatenbankException {
        try {
            // Имитация подключения
            System.out.println("Verbinde zu MySQL: " + verbindungsString);
            Thread.sleep(1000); // Имитируем задержку сети
            verbunden = true;
            System.out.println("Verbindung hergestellt");
        } catch (InterruptedException e) {
            throw new DatenbankException("Verbindung unterbrochen", e);
        }
    }
    
    @Override
    public void trennen() {
        if (verbunden) {
            System.out.println("Verbindung getrennt");
            verbunden = false;
        }
    }
    
    @Override
    public boolean istVerbunden() {
        return verbunden;
    }
    
    @Override
    public List<Map<String, Object>> abfragen(String sql) throws DatenbankException {
        if (!verbunden) {
            throw new DatenbankException("Nicht verbunden");
        }
        
        System.out.println("Führe aus: " + sql);
        
        // Имитируемый результат
        List<Map<String, Object>> ergebnis = new ArrayList<>();
        Map<String, Object> zeile = new HashMap<>();
        zeile.put("id", 1);
        zeile.put("name", "Testdaten");
        ergebnis.add(zeile);
        
        return ergebnis;
    }
    
    @Override
    public int ausfuehren(String sql) throws DatenbankException {
        if (!verbunden) {
            throw new DatenbankException("Nicht verbunden");
        }
        
        System.out.println("Führe aus: " + sql);
        return 1; // Имитируемое количество затронутых строк
    }
}

// Использование API
public class ApiDemo {
    public static void main(String[] args) {
        // Полиморфное использование через интерфейс
        DatenbankSchnittstelle db = new MySQLDatenbank("jdbc:mysql://localhost/test");
        
        try {
            // Работаем через интерфейс
            db.verbinden();
            
            if (db.istVerbunden()) {
                List<Map<String, Object>> ergebnis = db.abfragen("SELECT * FROM kunden");
                System.out.println("Ergebnis: " + ergebnis.size() + " Zeilen");
                
                int rows = db.ausfuehren("UPDATE kunden SET status = 'active'");
                System.out.println("Betroffene Zeilen: " + rows);
            }
            
        } catch (DatenbankException e) {
            System.err.println("Datenbankfehler: " + e.getMessage());
        } finally {
            db.trennen();
        }
    }
}

5. Пример Web-API

// REST API Controller (Spring Boot пример)
@RestController
@RequestMapping("/api/kunden")
public class KundenAPI {
    
    private final KundenService service;
    
    public KundenAPI(KundenService service) {
        this.service = service;
    }
    
    // GET /api/kunden/{id}
    @GetMapping("/{id}")
    public ResponseEntity<Kunde> getKunde(@PathVariable Long id) {
        try {
            Kunde kunde = service.findeKundeById(id);
            return ResponseEntity.ok(kunde);
        } catch (KundeNotFoundException e) {
            return ResponseEntity.notFound().build();
        }
    }
    
    // POST /api/kunden
    @PostMapping
    public ResponseEntity<Kunde> createKunde(@RequestBody Kunde kunde) {
        Kunde erstellterKunde = service.erstelleKunde(kunde);
        return ResponseEntity.status(HttpStatus.CREATED).body(erstellterKunde);
    }
    
    // PUT /api/kunden/{id}
    @PutMapping("/{id}")
    public ResponseEntity<Kunde> updateKunde(@PathVariable Long id, @RequestBody Kunde kunde) {
        try {
            Kunde aktualisierterKunde = service.aktualisiereKunde(id, kunde);
            return ResponseEntity.ok(aktualisierterKunde);
        } catch (KundeNotFoundException e) {
            return ResponseEntity.notFound().build();
        }
    }
    
    // DELETE /api/kunden/{id}
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteKunde(@PathVariable Long id) {
        service.loescheKunde(id);
        return ResponseEntity.noContent().build();
    }
}

// Модель данных
class Kunde {
    private Long id;
    private String name;
    private String email;
    private LocalDate geburtsdatum;
    
    // Getter и Setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public LocalDate getGeburtsdatum() { return geburtsdatum; }
    public void setGeburtsdatum(LocalDate geburtsdatum) { this.geburtsdatum = geburtsdatum; }
}

Рекомендуемая литература: объектно-ориентированное программирование

Keine Bücher für Kategorie "objektorientierte-programmierung" gefunden.

Концепции OOP в обзоре

Инкапсуляция

// Данные и методы объединяются в одну единицу
public class Bankkonto {
    private double kontostand;  // Приватные данные
    
    public void einzahlen(double betrag) {  // Публичный метод
        if (betrag > 0) {
            kontostand += betrag;
        }
    }
    
    public double getKontostand() {
        return kontostand;
    }
}

Абстракция

// Сложная реальность упрощается
abstract class Fahrzeug {
    protected String marke;
    
    public abstract void beschleunigen();
    public abstract void bremsen();
    
    public void anzeigen() {
        System.out.println("Fahrzeug: " + marke);
    }
}

Полиморфизм

// Один интерфейс, множество реализаций
interface Tier {
    void macheLaut();
}

class Hund implements Tier {
    public void macheLaut() {
        System.out.println("Wuff!");
    }
}

class Katze implements Tier {
    public void macheLaut() {
        System.out.println("Miau!");
    }
}

// Использование
Tier tier1 = new Hund();
Tier tier2 = new Katze();

tier1.macheLaut(); // Wuff!
tier2.macheLaut(); // Miau!

Стратегии персистентности

Сериализация

  • Java Serialization: интерфейс Serializable
  • JSON: удобочитаемый, платформо-независимый формат
  • XML: структурированный, с метаданными
  • Binary: компактный, быстрый

Персистентность на основе БД

  • Реляционные БД: структурированные данные с SQL
  • NoSQL БД: гибкие документы или ключ-значение
  • ORM: Object-Relational Mapping
  • JPA/Hibernate: Java Persistence API

Облачная персистентность

  • Object Storage: S3, Azure Blob Storage
  • Databases-as-a-Service: Firebase, Supabase
  • Кеширование: Redis, Memcached

Типы API

Программные интерфейсы

  • Local APIs: методы в одной программе
  • Library APIs: внешние библиотеки
  • Framework APIs: Spring, Django, React

Web-API

  • REST: HTTP-методы, коды состояния
  • GraphQL: гибкий язык запросов
  • gRPC: высокопроизводительный RPC
  • WebSocket: общение в реальном времени

Платформенные API

  • OS APIs: Windows, Linux, macOS
  • Mobile APIs: Android, iOS
  • Cloud APIs: AWS, Azure, GCP

Преимущества и недостатки

Преимущества концепций OOP

  • Структурирование: четкая организация кода
  • Переиспользование: компоненты можно применять многократно
  • Поддерживаемость: модульная структура облегчает изменения
  • Тестируемость: изолированные компоненты легко тестировать
  • Масштабируемость: системы могут расти

Недостатки

  • Сложность: издержки при малых проектах
  • Кривая обучения: много концепций для понимания
  • Производительность: иногда медленнее, чем процедурный код
  • Переусложнение: риск излишней сложности

Часто встречающиеся вопросы

  1. В чём разница между атрибутом и методом? Атрибуты это свойства/данные, методы это поведение/функции объекта.

  2. Объясните понятие сообщение в OOP! Сообщение это взаимодействие между объектами, обычно реализуется как вызов метода.

  3. Что означает персистентность в программировании? Постоянное хранение данных, чтобы они были доступны в течение нескольких запусков программы.

  4. Для чего служат интерфейсы? Определяют контракты между компонентами, позволяют ослабить связанность и обеспечить полиморфизм.

Основные источники

  1. https://de.wikipedia.org/wiki/Objektorientierte_Programmierung
  2. https://docs.oracle.com/javase/tutorial/java/concepts/
  3. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/

Продолжение пути обучения OOP

Следующая статья в пути OOP рассмотрит OOP инкапсуляция: основы, информационное скрывание и видимость , как инкапсуляция скрывает внутренние состояния.

Назад к блогу
Share:

Похожие статьи