개인 공부

객체지향 프로그래밍 OOP

orin602 2025. 1. 15. 17:26

개인공부 : 객체지향!

 

객체지향(Object-Oriented Programming, OOP)은 소프트웨어 개발 방법 중 하나로, 객체를 프로그램 내에서 Object라는 단위로 모델링해 시스템을 설계하는 방식을 말하며, 이러한 객체지향은 복잡한 시스템을 쉽게 이해하고 유지보수할 수 있도록 도와주고, 여러 가지 객체지향 원칙을 기반으로 시스템을 구성합니다.

 

핵심 개념

  • 클래스(Class)
    • 클래스는 객체를 만들기 위한 틀. 객체가 가질 성(필드)과 행동(메서드)를 정의합니다.
  • 객체(Object)
    • 객체는 클래스로부터 생성된 실체. 클래스에서 정의한 속성값과 메서드를 가지고 있고, 실제로 동작하는 프로그램의 기본 단위입니다.
  • 상속(Inheritance)
    • 상속은 기존 클래스의 속성이나 행동을 재사용해 새로운 클래스를 만드는 기능. 상속을 통해 코드의 중복을 줄이고, 계층적인 관계를 설정할 수 있습니다.
  • 다형성(Polymorphism)
    • 다형성은 같은 이름의 메서드가 서로 다른 방식으로 동작하는 특성. 코드를 유연하고 확장 가능하게 만들 수 있습니다.
  • 캡슐화(Encapsulation)
    • 캡슐화는 객체의 내부 상태를 보호하고, 외부에서 직접 접근하지 못하도록 정보 은닉하는 원칙. 필요한 데이터와 메서드만 공개해 객체의 사용성을 높이고, 유지보수를 쉽게 합니다.
  • 추상화(Abstraction)
    • 추상화는 시스템에서 불필요한 세부 정보를 숨기고 중요한 부분만 노출시킨다. 복잡성을 줄이고, 객체의 사용을 단순화합니다.

 

장점

  • 재사용성 : 상속을 통해 기존 코드를 재사용할 수 있어 중복을 줄이고, 시스템을 확장할 수 있다.
  • 유지보수 용이 : 캡슐화 덕분에 객체의 내부 구현을 변경해도 외부에 미치는 영향을 최소화할 수 있다.
  • 확장성 : 다형성 및 상속을 통해 시스템을 확장할 때 유연하게 대응할 수 있다.
  • 효율성 : 추상화된 인터페이스를 통해 필요한 부분만 사용할 수 있어 시스템의 효율성을 높일 수 있다.

프로젝트 생성

프로젝트 생성 단계

 

클래스와 객체 생성

  • Getter 및 Setter 생성은 (Alt + Shift + s)로 간편하게 생성 가능.

package com.demo.domain;

public class Book {

	// 속성(필드)
	private String title;	// 제목
	private String author;	// 저자
	private double price;	// 가격
	
	// 생성자
	public Book(String title, String author, double price) {
		this.title = title;
		this.author = author;
		this.price = price;
	}

	// Getter, Setter
	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}
	
	// 책 정보 출력 메서드
	public void bookInfo() {
		System.out.println("제목 : " + title + " 저자 : " + author + " 가격 : " + price);
	}
}

 

package com.demo.domain;

public class Main {

	public static void main(String[] args) {
		// 객체 생성
		Book book1 = new Book("책1", "저자1", 12000.00);
		book1.bookInfo();
		
	}
}
  • 프로젝트 실행 (Alt + Shift + X, J)로 실행

 

상속(Inheritance) 적용하기

  • Book2 클래스 생성 및 상속.

package com.demo.domain;

public class Book2 extends Book{

	private String file;
	
	public Book2(String title, String author, double price, String file) {
		super(title, author, price);
		this.file = file;
	}

	public String getFile() {
		return file;
	}

	public void setFile(String file) {
		this.file = file;
	}
	
	@Override
	public void bookInfo() {
		super.bookInfo();
		System.out.println("파일 : " + file);
	}
}
  • extends Book : 상속을 의미하고,  상속은 부모 클래스의 속성과 메서드를 자식 클래스가 물려받는 개념입니다. 자식 클래스는 부모 클래스의 기능을 그대로 사용하거나, 필요에 따라 변경(오버라이드)할 수 있습니다.
  • public Book2(String title, String author, double price, String file) : 이 생성자는 부모클래스인 Book의 생성자를 호출해 title, author, price값을 부모 클래스의 속성에 설정하고, 추가 속성으로 file을 추가함.
  • @Override : 부모 클래스인 Book에서 정의한 bookInfo() 메서드를 오버드라이브해 Book2 클래스에서 구현하고 있음. (오버드라이브는 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것.
  • super.bookInfo() : 부모 클래스인 Book의 bookInfo() 메서드를 호출합니다. 이를 통해 부모 클래스에서 정의된 책의 정보(제목, 저자, 가격 등)가 먼저 출력됩니다.
  • System.out.println("파일 : " + file) : 그 후, Book2 클래스에서 추가된 file 속성을 출력합니다. 즉, 전자책 파일에 대한 정보를 출력합니다
package com.demo.domain;

public class Main {

	public static void main(String[] args) {
		// 객체 생성
//		Book book1 = new Book("책1", "저자1", 12000.00);
//		book1.bookInfo();
		
		Book book2 = new Book2("책2", "저자2", 12000.00, "책2.pdf");
		book2.bookInfo();
	}
}

실행 결과

 

다형성(Polymorphism) 적용하기

package com.demo.domain;

public class Main {

	public static void main(String[] args) {
		// 객체 생성
		Book book1 = new Book("책 1", "저자 1", 12000.00);
//		book1.bookInfo();
		
		Book book2 = new Book2("책 2", "저자 2", 13000.00, "책 2.pdf");
//		book2.bookInfo();
		
		// 다형성 : 부모 타입의 변수로 자식 클래스 객체를 참조.
		book1.bookInfo();
		book2.bookInfo();
	}
}

실행 결과

book1Book객체, book2Book2객체지만, 둘 다 Book타입으로 선언되어서 Book클래스에서 정의한 메서드 bookInfo()를 호출할 수 있다. 이 때 book2는 자식 클래스 Book2의 메서드를 호출해 파일 정보도 출력된다.

 

캡슐화(Encapsulation)

  • 캡슐화는 객체의 속성을 private으로 설정하고, 수정하거나 접근할 수 있는 메서드를 제공해 내부 구현을 숨기는 방식.

Book 클래스에서의

private String title;	// 제목
private String author;	// 저자
private double price;	// 가격

 

Book2 클래스에서의 

private String file;

 

속성(필드)는 private로 선언되어 외부에서 직접 접근할 수 없다.

>> Getter와 Setter 메서드를 제공해서 set...() 메서드는 값을 수정하기 전 검증 로직을 추가해 유효성을 체크하고, get...()메서드는 값을 안전하게 반환.

 

추상화(Abstraction)

  • 추상화는 객체의 중요한 기능만 외부에 드러내고, 복잡한 세부 사항은 숨기는 개념으로 추상 클래스나 인터페이스를 사용할 수 있다.
  • 추상 클래스는 구현되지 않은 메서드를 포함할 수 있고, 이 메서드는 자식 클래스에서 구현해야 한다.
package com.demo.domain;

// 부모 클래스 : 추상화된 클래스
public abstract class Book {

    // 속성(필드)
    private String title;   // 제목
    private String author;  // 저자
    private double price;   // 가격
    
    // 생성자
    public Book(String title, String author, double price) {
        this.title = title;
        this.author = author;
        this.price = price;
    }

    // Getter, Setter
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    // 책 정보 출력 메서드 - 추상화된 메서드
    public abstract void bookInfo();
}

추상화된 메서드 bookInfo() : 자식 클래스에서 구체적인 동작을 구현하도록 강제한다.

부모 클래스에서는 메서드 이름만 정의하고, 실제 출력 방식이나 구체적인 구현은 자식 클래스에서 결정.

package com.demo.domain;

// 자식 클래스 : 구체적인 구현을 담당
public class Book2 extends Book {

    private String file;  // 추가 속성 (eBook 파일명)

    public Book2(String title, String author, double price, String file) {
        super(title, author, price);
        this.file = file;
    }

    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public void bookInfo() {
        // 부모 클래스의 기본 정보를 출력한 후, 자식 클래스의 고유 속성 출력
        System.out.println("제목 : " + getTitle() + " 저자 : " + getAuthor() + " 가격 : " + getPrice());
        System.out.println("파일 : " + file);  // 자식 클래스에서 추가된 기능
    }
}

 

추상화된 bookInfo() 메서드 사용.

package com.demo.domain;

public class Main {

    public static void main(String[] args) {
        // 부모 타입으로 자식 객체를 다루는 다형성
        Book book1 = new Book2("책 1", "저자 1", 12000.00, "책1.pdf");

        // bookInfo() 메서드는 자식 클래스에서 구현한 구체적인 내용을 출력
        book1.bookInfo();  // 자식 클래스의 bookInfo() 호출
    }
}

결과

추상화를 통해 부모 클래스에서 공통된 부분을 정의하고, 자식 클래스에서 구체적인 동작을 구현할 수 있습니다. 이렇게 하면, 코드를 재사용하고 유지보수를 용이하게 만들 수 있습니다.