무지개곰
article thumbnail
반응형

객체 지향 프로그래밍(Object Oriented Programming, OOP)은 소프트웨어 개발 패러다임 중 하나로, 현실 세계의 사물과 개념을 소프트웨어 객체로 모델링하여 문제를 해결하는 방법입니다. 객체 지향 프로그래밍의 개념과 주요 용어에 대하여 알아보겠습니다. 설명은 java를 기준으로 하고 있습니다.

목차

객체지향 프로그래밍(OOP)이란?

클래스와 객체의 차이

캡슐화란?

상속이란?

추상 클래스와 인터페이스


객체지향 프로그래밍(OOP)이란?

프로그램을 독립적인 객체의 집합으로 구성하는 방법입니다. 각 객체는 데이터와 해당 데이터를 처리하는 메서드로 구성되며, 객체 간의 상호작용을 통해 프로그램이 동작합니다. 이는 현실 세계의 객체들의 관계와 유사하게 모델링 됩니다.


클래스와 객체의 차이

클래스는 객체를 생성하기 위한 설계도이며, 객체는 클래스의 인스턴스입니다. 클래스는 속성을 정의하는 필드와 동작을 정의하는 메서드로 구성됩니다. 객체는 클래스의 속성을 가지고 있으며, 해당 클래스의 메서드를 호출하여 수행할 수 있습니다. 예시 코드는 아래와 같습니다.

class Car {
    // 클래스의 속성
    public String brand;
    public String color;
    
    // 클래스의 메서드
    public void start() {
        System.out.println("Car started!");
    }
    
    public void stop() {
        System.out.println("Car stopped!");
    }
}

public class Main {
    public static void main(String[] args) {
        // Car 클래스의 객체 생성
        Car myCar = new Car();
        
        // 객체의 속성 설정
        myCar.brand = "Toyota";
        myCar.color = "Red";
        
        // 객체의 메서드 호출
        myCar.start();  // 출력: "Car started!"
        myCar.stop();   // 출력: "Car stopped!"
    }
}

Car class는 자동차를 나타내는 설계도입니다. Car mayCar = new Car()를 통하여 Car 클래스의 인스턴스인 myCar라는 객체를 생성하고 myCar.brand, myCar.color을 통하여 속성을 정의하고 start, stop이라는 메서드를 호출할 수 있습니다.


캡슐화란?

캡슐화는 객체지향 프로그래밍에서 정보 은닉과 관련된 개념으로, 객체의 상태와 동작을 외부로부터 감추는 것을 의미합니다. 객체는 내부 구현의 세부사항을 숨기고, 외부에서는 공개된 인터페이스를 통해 객체와 상호작용합니다.

class BankAccount {
    private String accountNumber;
    private double balance;
    
    public void deposit(double amount) {
        // 계좌 잔액 증가
        balance += amount;
    }
    
    public void withdraw(double amount) {
        // 계좌 잔액 감소
        if (balance >= amount) {
            balance -= amount;
        } else {
            System.out.println("Insufficient balance!");
        }
    }
    
    public double getBalance() {
        return balance;
    }
}

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        account.deposit(1000);
        account.withdraw(500);
        
        double balance = account.getBalance();
        System.out.println("Current balance: " + balance);
    }
}

예시코드를 보면 accountNumber와 balance의 접근제어자가 private으로 되어있습니다. 따라서 Car의 예시처럼 account.balance = 1000과 같이 외부에서 직접 접근하여 balance를 조절할 수 없습니다. private의 값을 수정하기 위해서 class에 정의되어 있는 인터페이스를 이용하게 되는데 예시에서 deposit, withdraw가 이에 해당됩니다. balance를 확인하는 경우도 account.balance로 확인이 불가능하여 getBalance를 이용하여 값을 얻어야 합니다.


상속이란?

상속은 객체 지향 프로그래밍에서 새로운 클래스를 생성할 때 이미 존재하는 클래스의 속성과 동작을 상속받는 개념입니다. 부모 클래스(상위 클래스 또는 슈퍼 클래스)의 속성과 동작을 자식 클래스(하위 클래스 또는 서브 클래스)에서 재사용할 수 있습니다.

class Animal {
    public void eat() {
        System.out.println("Animal is eating...");
    }
}

class Dog extends Animal {
    public void bark() {
        System.out.println("Dog is barking...");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();   // 출력: "Animal is eating..."
        dog.bark();  // 출력: "Dog is barking..."
    }
}

예시 코드에서 Animal 클래스는 동물을 나타내며 eat이라는 메서드를 가지고 있는 클래스입니다. Dog 클래스는 Animal 클래스를 상속받아 Animal의 정보를 사용할 수 있습니다. 또한 bark라는 메서드를 추가적으로 정의하였습니다. Dog는 Animal을 상속받았기 때문에 eat메서드도 사용이 가능하고 bark 메서드도 사용할 수 있습니다.


추상 클래스와 인터페이스

추상 클래스와 인터페이스 모두 상속과 다형성을 지원하기 위한 개념입니다. 그러나 이 둘 사이에는 몇 가지 차이점이 있습니다.

추상 클래스

일반적인 클래스와 유사하지만, 추상 메서드를 포함할 수 있습니다. 추상 메서드는 구현이 없는 메서드로, 하위 클래스에서 반드시 구현되어야 합니다. 또한 추상 클래스도 클래스이기에 자식은 하나의 클래스만 상속받을 수 있습니다.

 

추상 클래스 구현

클래스가 추상 클래스를 상속받을 때 extends 키워드를 사용합니다.

abstract class Animal {
    public abstract void makeSound();
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();

        dog.makeSound();  // 출력: "Woof!"
    }
}

인터페이스

메서드의 선언만을 가지고 있으며, 구현을 갖지 않습니다. 인터페이스는 일종의 계약으로, 클래스가 반드시 구현해하는 메서드를 정의합니다. 추상클래스와는 다르게 다중 상속을 지원하여 여러 인터페이스를 동시에 구현할 수 있습니다.

 

인터페이스 구현

클래스가 인터페이스를 구현할 때는 implements 키워드를 사용하며, 인터페이스에서 선언한 모든 메서드를 구현해야 합니다.

interface Drawable {
    void draw();
}

class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Main {
    public static void main(String[] args) {
        Drawable circle = new Circle();

        circle.draw();     // 출력: "Drawing a circle"
    }
}

다형성이란?

객체 지향 프로그래밍에서 중요한 개념 중 하나로, 동일한 메서드를 호출하지만 실제로 실행되는 메서드가 객체의 타입에 따라 다르게 동작하는 특성을 다형성이라고 합니다. 다형성은 코드의 유연성과 재사용성을 높여주며 객체 간의 관계를 더욱 유연하게 다룰 수 있게 해 줍니다.

class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

        animal1.makeSound(); // 출력: "Dog barks"
        animal2.makeSound(); // 출력: "Cat meows"
    }
}

위의 예시에서 Animal 클래스는 makeSound 메서드를 가지고 있습니다. Dog와 Cat는 Animal을 상속받고 makeSound 메서드를 재정의(오버라이딩)하여 각 동물 소리를 출력합니다.

Animal 타입의 변수 animal1과 animal2에 Dog와 Cat를 할당하고 makeSound를 호출하면 Animal 클래스의 makeSound를 호출하는 것으로 보이지만 실제로는 오버라이딩 된 메서드가 호출됩니다. 이러한 것을 다형성이라고 합니다.

반응형
profile

무지개곰

@무지개곰

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!