[Java] 객체지향 프로그래밍

Junkyu_Kang·2024년 6월 14일

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 소프트웨어 설계 패러다임 중 하나로, 데이터를 객체(object)라는 단위로 묶어 이를 중심으로 프로그램을 구성하는 방법입니다. OOP는 코드의 재사용성, 확장성, 유지보수성을 높이기 위해 도입된 개념으로, 주요 특징으로는 캡슐화, 상속, 다형성, 추상화가 있습니다.

객체지향 프로그래밍의 핵심 개념

객체(Object):

객체는 상태(state)와 행동(behavior)을 가진 소프트웨어 구성 요소입니다. 상태는 객체의 속성을 나타내는 데이터(필드, 변수 등)로, 행동은 객체가 수행할 수 있는 동작(메서드, 함수 등)으로 정의됩니다.
예: 자동차 객체는 속성으로 색상, 모델, 속도를 가질 수 있고, 행동으로는 가속, 감속, 방향 전환 등을 가질 수 있습니다.

클래스(Class):

클래스는 객체를 생성하기 위한 설계도(blueprint)입니다. 객체는 클래스의 인스턴스(instance)로, 클래스는 객체의 속성과 행동을 정의합니다.
예: Car 클래스는 색상, 모델, 속도를 속성으로 가지며, 가속, 감속, 방향 전환 메서드를 가질 수 있습니다.
객체지향 프로그래밍의 주요 원칙

캡슐화(Encapsulation):

캡슐화는 객체의 데이터를 외부로부터 보호하고, 데이터에 접근하는 메서드를 통해서만 조작할 수 있도록 하는 원칙입니다. 이를 통해 데이터의 무결성을 유지하고, 객체 내부 구현을 숨겨 외부에서 객체를 쉽게 사용할 수 있도록 합니다.
접근 제어자(Access Modifiers): private, protected, public 등을 사용하여 클래스 멤버(필드, 메서드 등)의 접근 범위를 제어합니다.
예: private 접근 제어자를 사용하여 클래스의 속성을 외부에서 직접 접근하지 못하게 하고, public 메서드를 통해서만 속성에 접근하도록 합니다.

public class Car {
    private String color;
    private int speed;
    
    public String getColor() {
        return color;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public int getSpeed() {
        return speed;
    }
    
    public void setSpeed(int speed) {
        if (speed >= 0) {
            this.speed = speed;
        }
    }
}

상속(Inheritance):

상속은 기존 클래스(부모 클래스, 슈퍼 클래스)를 확장하여 새로운 클래스(자식 클래스, 서브 클래스)를 만드는 원칙입니다. 자식 클래스는 부모 클래스의 속성과 행동을 물려받아 재사용할 수 있으며, 필요에 따라 새로운 속성과 행동을 추가하거나 변경할 수 있습니다.
상속을 통해 코드의 재사용성을 높이고, 계층 구조를 통해 클래스 간의 관계를 명확히 할 수 있습니다.
예: Vehicle 클래스를 상속받아 Car 클래스와 Bike 클래스를 만드는 경우, 두 클래스는 공통된 속성과 메서드를 상속받습니다.

public class Vehicle {
    protected String color;
    protected int speed;
    
    public void start() {
        System.out.println("Vehicle started");
    }
    
    public void stop() {
        System.out.println("Vehicle stopped");
    }
}

public class Car extends Vehicle {
    private int doors;
    
    public void setDoors(int doors) {
        this.doors = doors;
    }
    
    public int getDoors() {
        return doors;
    }
    
    @Override
    public void start() {
        System.out.println("Car started");
    }
}

다형성(Polymorphism):

다형성은 동일한 메시지에 대해 서로 다른 방식으로 응답할 수 있는 능력을 의미합니다. 이는 메서드 오버로딩(Method Overloading)과 메서드 오버라이딩(Method Overriding)을 통해 구현됩니다.
메서드 오버로딩: 같은 이름의 메서드를 여러 개 정의하지만, 매개변수의 타입이나 개수가 다릅니다.
메서드 오버라이딩: 부모 클래스의 메서드를 자식 클래스에서 재정의하여 사용할 수 있습니다.
예: Animal 클래스의 makeSound 메서드를 Dog 클래스와 Cat 클래스에서 다르게 구현할 수 있습니다.

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

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

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

추상화(Abstraction):

추상화는 복잡한 시스템에서 필요한 부분만을 모델링하여 단순화하는 원칙입니다. 이를 통해 불필요한 세부 사항을 숨기고 중요한 속성 및 동작에 집중할 수 있습니다.
추상 클래스(Abstract Class)와 인터페이스(Interface)를 사용하여 추상화를 구현합니다.
추상 클래스: 일부 메서드가 구현되지 않은 클래스로, 자식 클래스에서 이를 구현해야 합니다.
인터페이스: 모든 메서드가 구현되지 않은 추상 타입으로, 이를 구현하는 클래스에서 모든 메서드를 구현해야 합니다.
예: Shape 추상 클래스를 만들고, 이를 상속받는 Circle과 Rectangle 클래스를 구현할 수 있습니다.

public abstract class Shape {
    protected String color;
    
    public abstract double calculateArea();
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public String getColor() {
        return color;
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
}

객체지향 프로그래밍의 장점

코드 재사용성:

상속을 통해 기존 코드를 재사용하고, 중복을 줄일 수 있습니다.
모듈화된 코드를 작성하여 여러 프로젝트에서 재사용할 수 있습니다.
유지보수성:

캡슐화를 통해 객체 내부 구현을 숨기고, 인터페이스를 통해 상호작용하도록 함으로써 코드의 수정이 용이합니다.
코드 변경이 다른 부분에 미치는 영향을 최소화할 수 있습니다.

확장성:

새로운 기능을 추가할 때 기존 코드를 변경하지 않고, 새로운 클래스와 메서드를 추가하여 확장할 수 있습니다.
다형성을 활용하여 다양한 객체를 동일한 방식으로 처리할 수 있습니다.

모델링 용이성:

현실 세계의 개체와 상호작용을 객체와 클래스 형태로 쉽게 모델링할 수 있습니다.
복잡한 시스템을 더 쉽게 이해하고 설계할 수 있습니다.
객체지향 프로그래밍은 이러한 개념과 원칙을 통해 복잡한 소프트웨어 시스템을 더 쉽게 설계, 구현 및 유지보수할 수 있도록 도와줍니다. Java는 객체지향 프로그래밍을 지원하는 대표적인 언어 중 하나로, 이러한 개념을 효과적으로 활용할 수 있는 다양한 기능과 도구를 제공합니다.

profile
강준규

0개의 댓글