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

728x90

출처 : www.tutorialspoint.com

 

안녕하세요. 오늘은 공부해도 시간 지나면 까먹어버리는 객체지향 프로그래밍에 대해 작성해보도록 하겠습니다.

 

 

 

OOP(Object-Oriented Programming)란?

  • 프로그램을 객체라는 독립적인 단위로 나누어 설계하고 개발하는 프로그래밍
  • 객체는 데이터(속성)와 메서드(행동)을 포함하며 이 두 가지를 하나로 묶어 프로그램을 구조화하며, 이를 통해 코드의 재사용성과 유지보수성을 높이고 현실 세계의 문제를 프로그램으로 자연스럽게 표현할 수 있음
  • 4가지 주요 특징으로는 캡슐화, 상속성, 다형성, 추상화가 있음

 

 

OOP의 특징

1. 캡슐화(Encapsulation)

객체의 데이터(속성)와 이를 처리하는 메서드(행동)을 하나로 묶고 외부에서 직접 접근할 수 없도록 제한하는 개념

데이터를 보호하고 객체 내부의 구현 세부 사항을 감추는 역할을 함

 

장점

  • 데이터 무결성 유지 : 외부에서 직접 데이터를 변경하지 못하도록 보호함
  • 코드의 재사용성과 유지보수성 증가 : 내부 구현 변경이 외부 코드에 영향을 미치지 않음

 

구현 방식

  • 접근 제어자를 사용하여 데이터 접근을 제한함
    • private : 클래스 내부에서만 접근 가능. 외부 접근 완전 차단(※정보 은닉의 핵심)
    • protected : 같은 패키지 또는 상속받은 클래스에서만 접근 가능
    • public : 어디에서나 접근 가능. 외부에 공개

※ 정보 은닉 : 캡슐화의 한 요소이며, 데이터 보호뿐 아니라 객체 내부 구현의 독립성을 보장함(객체 내부의 구현 세부 사항을 감추고, 외부에서 필요한 정보나 기능만 공개하는 개념)

  • Getter/Setter 메서드로 외부에서 데이터에 간접적으로 접근하도록 함

 

예시

class Bank {
    private double balance; // 외부에서 직접 접근 불가

    // Getter - balance 조회
    public double getBalance() {
        return balance;
    }
    
    // Setter - balance 수정
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Bank account = new Bank();
        account.deposit(1000); // 1000원 입금
        account.withdraw(500); // 500원 출금
        System.out.println(account.getBalance()); // 500.0
    }
}

 

 

 

2. 상속성(Inheritance)

기존 클래스(부모 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스)가 물려받아 사용하는 것

 

장점

  • 코드 재사용성 : 공통된 기능은 부모 클래스에 정의하고 자식 클래스는 추가 기능만 구현
  • 유지보수 용이성 : 수정 사항이 부모 클래스에만 적용되면 자식 클래스에서도 반영됨
  • 확장성 : 기존 클래스의 기능을 확장하거나 수정 가능

 

구현 방식

  • extends 키워드 사용
  • 부모 클래스의 메서드를 자식 클래스에서 재정의(오버라이딩) 가능

 

예시

class Animal {
    public void eat() {
        System.out.println("먹다.");
    }
}

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

    @Override
    public void eat() {
    	System.out.println("강아지가 밥을 먹다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat(); // 강아지가 밥을 먹다.
        dog.bark(); // 짖다.
    }
}

 

 

 

3. 다형성(Polymorphism)

같은 메서드 호출이나 객체 참조가 상황에 따라 다른 방식으로 동작하는 것을 의미함

 

유형

  • 메서드 오버라이딩(Method Overriding) : 부모 클래스의 메서드를 자식 클래스에서 재정의
  • 메서드 오버로딩(Method Overloading) : 같은 이름의 메서드를 매개변수의 타입이나 개수 등에 따라 다르게 정의

 

장점

  • 유연성 : 같은 코드로 다양한 객체를 처리
  • 확장성 : 객체에 따라 다른 동작을 정의 가능

 

예시1 (오버라이딩)

// 오버라이딩 예시
// 부모 클래스
class Shape {
    public void draw() {
        System.out.println("도형을 그린다.");
    }
}

// 자식 클래스
class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("원을 그린다.");
    }
}

class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("사각형을 그린다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape shape;

        shape = new Circle();
        shape.draw(); // 원을 그린다.

        shape = new Rectangle();
        shape.draw(); // 사각형을 그린다.
    }
}

 

예시2 (오버로딩)

// 오버로딩 예시
class Shape {
    // 기본 draw 메서드
    public void draw() {
        System.out.println("도형을 그린다.");
    }

    // 오버로딩된 draw 메서드 (매개변수 추가)
    public void draw(String color) {
        System.out.println(color + " 색상의 도형을 그린다.");
    }

    // 오버로딩된 draw 메서드 (매개변수 타입 다름)
    public void draw(int size) {
        System.out.println("크기가 " + size + "인 도형을 그린다.");
    }

    // 오버로딩된 draw 메서드 (매개변수 개수 다름)
    public void draw(String color, int size) {
        System.out.println(color + " 색상의 크기 " + size + "인 도형을 그린다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape shape = new Shape();

        // 기본 draw 메서드 호출
        shape.draw(); // 도형을 그린다.

        // 오버로딩된 draw 메서드 호출
        shape.draw("빨간색"); // 빨간색 색상의 도형을 그린다.
        shape.draw(10);       // 크기가 10인 도형을 그린다.
        shape.draw("파란색", 20); // 파란색 색상의 크기 20인 도형을 그린다.
    }
}

 

오버라이딩과 오버로딩의 차이점

구분 오버라이딩(Overriding) 오버로딩(Overloading)
목적 부모 클래스의 메서드를 재정의하여 동작을 변경함 같은 이름의 메서드를 다양한 매개변수로 제공
조건 메서드 이름, 매개변수, 반환 타입이 부모와 동일해야함 메서드 이름은 같고 매개변수의 개수나 타입이 달라야 함
대상 상속 관계에서 사용 같은 클래스 내에서 사용
사용 시점 다형성을 구현하기 위해 사용 편리한 메서드 호출을 위해 사용

 

 

 

4. 추상화(Abstraction)

복잡한 시스템에서 필요한 핵심 기능만 정의하고 세부 사항은 구현하지 않는 개념(실제 구현이 아닌 구조와 약속을 정의한다는 의미!)

 

장점

  • 코드의 가독성 향상 : 설계와 구현을 분리
  • 유지보수 용이성 : 구현을 변경해도 인터페이스는 유지 가능
  • 효율적 설계 : 공통된 인터페이스를 기반으로 다양한 구현체를 설계 가능

 

구현 방식

  • 추상 클래스(Abstract Class)
    • abstract 키워드 사용
    • 추상 메서드는 구현 없이 선언만 가능
  • 인터페이스(Interface)
    • 객체가 반드시 구현해야 할 메서드 목록을 정의

+) Java 8부터 인터페이스에 기본 메서드와 정적 메서드를 추가할 수 있음. 이를 통해 인터페이스도 일부 구현을 포함할 수 있게 되었지만, 본질적으로 객체 간 공통된 행동(규격)을 정의하는 목적은 변하지 않음!

 

예시1 (추상 클래스)

// 추상 클래스
abstract class Animal {
    abstract void sound(); // 추상 메서드
}

// 자식 클래스
class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("멍멍!");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("야옹!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.sound(); // 멍멍!

        Animal cat = new Cat();
        cat.sound(); // 야옹!
    }
}

 

예시2 (인터페이스)

interface Animal {
    void sound(); // 추상 메서드
}

// Dog 클래스는 Animal 인터페이스를 구현
class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("멍멍!");
    }
}

// Cat 클래스는 Animal 인터페이스를 구현
class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("야옹!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog(); // Animal 인터페이스 타입으로 Dog 객체 참조
        dog.sound(); // 멍멍!

        Animal cat = new Cat(); // Animal 인터페이스 타입으로 Cat 객체 참조
        cat.sound(); // 야옹!
    }
}

 

추상 클래스와 인터페이스의 차이점

구분 추상 클래스 인터페이스
목적 공통된 행동(메서드)과 속성(필드)을 정의 공통된 행동(메서드)의 규격을 정의
구현 여부 추상 메서드와 일반 메서드 모두 포함 가능 모든 메서드는 기본적으로 추상 메서드(Java 8부터는 기본 메서드와 정적 메서드도 가능)
다중 상속 다중 상속 불가(class MyClass extends AbstractClass) 다중 구현 가능(class MyClass implements InterfaceA, InterfaceB)
필드 private, protected 등 다양한 접근 제어자를 가진 필드 포함 가능 public static final (상수)만 허용
사용 시점 공통적인 빌드와 메서드(구현 포함)를 상속받아 사용할 때 객체 간 공통된 행동(규격)을 정의

 

 

 

정리

  • 캡슐화 : 데이터 보호 및 은닉 → Getter/Setter를 통해 무결성 유지
  • 상속성 : 코드 재사용 및 확장 → extends
  • 다형성 : 동일한 코드로 다양한 동작 구현 → 오버라이딩/오버로딩
  • 추상화 : 핵심만 정의하고 구현은 자식 클래스에 위임 → 추상 클래스와 인터페이스 활용 / abstract

 

 

 

 

728x90