IT개발및프로그래밍/자바

[자바 기초 #4] 객체지향 프로그래밍(OOP) 기초 - 클래스와 객체

devgodmj 2024. 11. 17. 17:50

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

객체지향 프로그래밍(OOP)은 프로그램을 객체라는 독립된 단위로 나누어 관리하는 방식입니다. 객체는 데이터(속성)와 그 데이터를 조작하는 함수(메서드)를 포함하고 있으며, 현실 세계의 사물을 코드로 표현하는 데 유용합니다.


OOP(Object-Oriented Programming)의 주요 개념

  • 클래스(Class): 객체를 만들기 위한 설계도
  • 객체(Object): 클래스를 기반으로 생성된 실제 데이터(인스턴스)
  • 속성(Attribute): 객체가 가지는 데이터(변수)
  • 행동(Method): 객체가 수행할 수 있는 기능(함수)

2. 클래스와 객체

클래스는 객체를 만들기 위한 청사진(=설계도=템플릿=기본구조=모형=뼈대)이며, 객체는 그 청사진을 기반으로 생성된 실제 데이터입니다. 예를 들어, Dog라는 클래스를 설계하면 실제 강아지인 dog1, dog2와 같은 객체를 만들 수 있죠.


클래스 선언하기

클래스를 만들 때는 class 키워드를 사용합니다.

public class Dog {
    // 속성
    String name;
    int age;
    
    // 행동(메서드)
    public void bark() {
        System.out.println(name + "가 짖습니다.");
    }
}

객체 생성하기

클래스를 만들었다면, 이제 그 클래스를 기반으로 객체를 생성할 수 있습니다. 객체는 new 키워드를 사용하여 생성합니다.

public class Main {
    public static void main(String[] args) {
        // Dog 클래스의 객체 생성
        Dog myDog = new Dog();
        myDog.name = "바둑이";
        myDog.age = 3;
        
        myDog.bark(); // 바둑이가 짖습니다.
    }
}

 

💡 myDog는 Dog 클래스의 인스턴스, 즉 객체입니다. myDog.name과 myDog.age로 속성에 접근할 수 있습니다.


3. 생성자(Constructor)

생성자는 객체를 생성할 때 초기화하는 특별한 메서드입니다. 생성자는 클래스와 이름이 같아야 하며, 객체 생성 시 자동으로 호출됩니다.


기본 생성자

아래 예제에서 생성자를 통해 객체 생성 시 기본값을 설정해 줍니다.

public class Dog {
    String name;
    int age;

    // 기본 생성자
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void bark() {
        System.out.println(name + "가 짖습니다.");
    }
}

생성자 활용 예제

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("바둑이", 3);
        myDog.bark(); // 바둑이가 짖습니다.
    }
}

 

결과

바둑이가 짖습니다.

4. 캡슐화와 접근 제어자

캡슐화는 객체의 속성을 보호하는 개념입니다. 자바에서는 public, private, protected 같은 접근 제어자를 사용해 외부 접근을 제어할 수 있습니다.


접근 제어자 종류

  • public: 모든 클래스에서 접근 가능
  • private: 해당 클래스 내부에서만 접근 가능
  • protected: 같은 패키지 또는 상속 관계에서 접근 가능

private를 이용한 캡슐화 예제

public class Dog {
    private String name;
    private int age;

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getter와 setter 메서드를 통해 접근 허용
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void bark() {
        System.out.println(name + "가 짖습니다.");
    }
}

예제: 이름과 나이를 출력하는 코드

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("바둑이", 3);
        
        System.out.println("이름: " + myDog.getName());
        System.out.println("나이: " + myDog.getAge());
        myDog.bark();
    }
}

 

결과

이름: 바둑이
나이: 3
바둑이가 짖습니다.

 


5. 상속과 다형성

상속은 기존 클래스의 기능을 물려받아 새로운 클래스를 만드는 기능입니다. 부모 클래스의 속성과 메서드를 자식 클래스가 상속받아 사용할 수 있죠. 또한, 다형성을 통해 상속받은 메서드를 재정의할 수 있습니다.


 

상속 기본 구조

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

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

상속 예제

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        
        myDog.eat(); // Animal 클래스의 메서드
        myDog.bark(); // Dog 클래스의 메서드
    }
}

 

결과

먹고 있습니다.
멍멍!

6. 오버라이딩 (메서드 재정의)

오버라이딩은 상속받은 메서드를 자식 클래스에서 재정의하여 사용할 수 있게 하는 기능입니다.


예제: 오버라이딩으로 행동 바꾸기

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

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

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

 

결과

멍멍!