객체지향(Object-Oriented Programming, OOP)

홍영창·2025년 4월 7일

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

객체지향(Object-Oriented Programming, OOP)은 소프트웨어를 개발하는 데 사용되는 프로그래밍 패러다임 중 하나 입니다. 객체지향 프로그래밍은 현실 세계의 객체(Object)와 그 객체들 간의 상호작용을 모델링하는 방식으로 소프트웨어를 설계하고 구현합니다. 이를 통해 코드의 재사용성, 유지보수성, 확장성을 향상시킬 수 있습니다.

OOP의 4가지 특성

캡슐화 (Encapsulation)

  • 캡슐화란 쉽게 말해 특정 클래스의 정보를 외부로 부터 숨기는것을 말한다.
    이를통해 외부로부터의 잘못된 접근을 막을수있다.

캡슐화는 어떻게 할수있을까?

자바에서는 대표적으로 protected , private 등의 접근제어자를 통해 구현이 가능하다.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Money {
    private static final Logger log = LoggerFactory.getLogger(Money.class);
    private int money;

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        if (money > 10000) { // money 가 유효한 값인지 확인한다.
            this.money = money;
        } else {
            log.error("유효하지 않은 값 입니다.");
        }
    }
}

이런식으로 private를 사용하여 Money클래스를 작성하면 잘못된 접근에 의해 값이 바뀌는것을 보호 할 수 있다. 따라서 money라는 맴버변수를 바로 접근할 수 없도록 private로 선언하고 데이터를 보호하는 것이다.

이렇게 보호된 money라는변수는 getter나 setter등의 메서드를 통해서만 간접적으로 접근이 가능하도록 하는 것이 바로 캡슐화이다.

추상화 (Abstraction)

  • 추상화란 공통적인 기능을 제공하면서 하위 클래스가 반드시 구현해야 하는 메서드를 명시하기 위해 사용 됩니다. 이를 통해 코드의 재사용성과 유지보수성을 늘릴수 있습니다.

어떤걸 추상화 해야할까?

예를 들어 내가 여러가지의 게임을 개발한다면? 공통적으로 명시해야하는 기능이 뭐가 있을까?

public abstract class Game {
	
	public final void play() {
    
		startPlay();

		endPlay();
	}


	//게임 시작
	abstract void startPlay();

	//게임 종료
	abstract void endPlay();

}

위 코드처럼 게임에서 항상 필요한 게임 시작과 종료 메서드를 미리 정의해서 사용하는것을 추상화 라고한다.

public class Football extends Game {

	@Override
	void startPlay() {
		System.out.println("Football 게임 시작");

	}

	@Override
	void endPlay() {
		System.out.println("Football 게임 종료");

	}

}

public class Baseball extends Game {


	@Override
	void startPlay() {
		System.out.println("Baseball 게임 시작");

	}

	@Override
	void endPlay() {
		System.out.println("Baseball 게임 종료");

	}

}

이처럼 Game이라는 추상클래스를 상속 받아 사용하면 코드의 재사용성을 늘릴수있다.

다형성(Polymorphism)

public class Animal {

	public Animal() {
		super();
		System.out.println("Animal() 생성자");
	}
	
	public void sound() {
		System.out.println("동물이 소리를 냅니다.");
	}
		
}

public class Cat extends Animal {

	public Cat() {
		super();
		System.out.println("Cat() 생성자");
	}

	@Override
	public void sound() {
		System.out.println("고양이가 야옹 합니다.");
	}
}


public class Dog extends Animal {

	public Dog() {
		super();
		System.out.println("Dog() 생성자");
	}
	
	@Override
	public void sound() {
		System.out.println("강아지가 멍멍 짖습니다.");
	}
}

public class Main {
	
	static final Logger log = LogManager.getFormatterLogger(Main.class);
	
	
	public static void main(String[] args) {
		
		Animal myCat = new Cat();
		Animal myDog = new Dog();
        myCat.sound();
		myDog.sound();

	}

}
  • 실행결과
Animal() 생성자
Cat() 생성자
강아지가 멍멍 짖습니다.
Animal() 생성자
Dog() 생성자
강아지가 멍멍 짖습니다.

위 메인 클래스를 실행하였을때 Animal타입으로 여러 객체를 처리하는것을 다형성 이라고 한다.

참조변수 형변환:

참조변수도 형변환 가능하다. 단 서로 상속관계 있는 클래스, 인터페이스에서만 가능하다.

자손 타입 -> 조상 타입(Up-casting): 형변환 생략 가능
조상 타입 -> 자손 타입(Down-casting): 형변환 생략 불가

상속성(Inheritance)

예를 들어 다음 코드처럼 클래스를 정의하고 상속받는다고 할때

public class Animal {
    String name;

    public void eat() {
        System.out.println(name + "가 먹는다.");
    }
}

public class Dog extends Animal {
    // Dog 클래스만의 필드
    String breed;

    // Dog 클래스만의 메서드
    public void bark() {
        System.out.println(name + "가 짖는다.");
    }
}

public class Main {

	public static void main(String[] args) {
		Dog dog =new Dog();
		dog.name = "몽이";//부모 클래스의 Animal의 필드
		
		dog.breed = "진돗개";//자식 클래스의 Dog의 필드
		
		dog.eat(); //부모 클래스의 Animal의 메서드 eat
		dog.bark();//자식 클래스의 Dog의 메서드 bark

	}

}
  • 실행 결과
몽이가 먹는다.
몽이가 짖는다

이처럼 상속(Inheritance)은 기존의 클래스를 재사용하여 새로운 클래스를 만드는 방법 입니다. 상속을 통해서 새로운 클래스(자식클래스, 서브클래스)가 기존 클래스(부모클래스, 슈퍼클래스)의 속성과 메서드를 상속 받아 재사용하거나 확장할 수 있습니다. 상속을 통해서 코드의 중복을 줄이고, 유지보수성을 높이는데 도움을 줍니다.

profile
안녕하세요.

0개의 댓글