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

가연우·2022년 5월 12일
0

Java Study

목록 보기
2/3

✨ OOP에 대해 공부한 것을 정리합니다.

🎲 OOP란?

Object Oriented Programming : 객체 지향 프로그래밍
현실 세계의 사물 및 개념들을 객체로 판단하고 그 객체들을 조립하여 프로그래밍하는 기법이다.
절차 지향 프로그래밍의 코드의 재사용성중복 제거가 가장 큰 목적이다.

  • 세상의 물체를 객체로 표현하고 이들 사이의 관계, 상호 작용을 프로그램으로 나타낸다.
  • 객체 추출, 객체들의 관계 결정, 이들의 상호 작용에 필요한 메서드와 필드를 설계 및 구현
  • 하나의 클래스가 여러 개의 인스턴스가 될 수 있다는 점이 가장 기본적인 재활용성이다.

🎈 특징

  1. 캡슐화(Encapsulation)
  2. 상속(Inheritance)
  3. 다형성(Polymorphism)
  4. 추상화(Abstraction)

캡슐화

  • 외부에 노출할 필요가 없는 정보들을 은닉한다. - 정보은닉
    - 정보은닉 : 필요 없는 정보는 외부에서 접근하지 못하도록 제한
  • 필요한 정보만 보여주도록 설계해야 한다는 뜻이다.

예시

class People{
	private String name;
    private int age;
    
    public getName(){
    	return name;
    }
    public getAge(){
    	return age;
    }
    
    public setName(String name){
    	this.name = name;
    }
    public setAge(int age){
    	this.age = age;
    }
}

캡슐화를 이해하는 가장 쉬운 예제는 클래스에서 private을 사용해 멤버변수의 접근 제어자를 설정하는 것이다. 접근 제어자를 통해 외부에서 직접 접근이 불가능하게 만들어주면 된다. 해당 멤버변수를 접근하기 위해 get, set 메서드를 통해 간접적으로 데이터에 접근할 수 있다.

상속

  • 부모 클래스가 자식 클래스에게 속성을 물려주는 것
  • 코드의 재사용성
  • 여러 개체들이 가진 공통된 특성을 부각시켜 하나의 개념으로 성립시키는 과정
  • extends 키워드 사용

예시

class People{
	String name;
    int age;
    
    People(String name, int age){
    	this.name = name;
        this.age = age;
    }
}

class Woman extends People{
	private String gender;
    
    Woman(String name, int age, String gender){
    	super(name, age);
        this.gender = gender;
    }
}

extends의 앞부분에 있는 클래스 명은 자식 클래스, extends 뒤에 있는 클래스는 부모 클래스이다. 부모 클래스는 자신이 가진 속성을 자식 클래스에서 사용할 수 있도록 한다. 자바에서는 단일 상속만 가능하다. 단, 부모 클래스를 구현할 때는 private인 필드는 상속되지 않는다는 점을 참고해야 한다. 이부분은 OOP의 특징인 캡슐화를 위반한다고 개인적으로 생각한다.


추상화

  • 객체의 공통된 속성들 중 필요한 부분을 찾아 클래스로 정의하는 기법
  • 구체적인 사물들의 공통적인 특징을 파악하여 하나의 개념으로 다루는 것

예시
편의상 get, set 메서드는 구현하지 않습니다.

public abstract class People{
	String name;
    int age;
    
	public void eat();
}

class Woman extends People{
	private String gender;
    
    Woman(String gender){
    	this.gender = gender;
    }
    
    @Override
    public void eat(){
    	System.out.println("음식을 먹다.");
    }
}

추상화는 공통된 요소를 클래스로 만든다. 이때 만들어진 클래스를 추상 클래스라고 하며 abstract를 붙여준다. 추상 클래스는 추상 메서드가 하나 이상 있어야 한다. 추상 메서드는 eat 메서드와 같이 구현되지 않은 메서드를 뜻한다.
추상 클래스를 상속받은 클래스는 반드시 추상 메서드를 구현해야 한다. 구현하는 메서드 위에는 @Override를 붙여준다. (이 어노테이션의 역할은 다형성을 설명하면서 같이 한다.)


다형성

  • 같은 형태이지만 다른 기능을 함
  • 서로 다른 클래스의 객체가 같은 메세지를 받았을 때 각자의 방식으로 동작하는 능력
  1. 오버라이딩(Overriding) : 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의
  2. 오버로딩(Overroading) : 같은 이름의 메서드 여러개를 가지면서 매개변수의 유형과 개수를 다르게 구현

성립 조건

구분오버로딩오버라이딩
메서드 이름동일동일
매개변수, 타입다름동일
리턴 타입동일하거나 다름동일

오버로딩 예시

class People{
	private String name;
    private int age;
    private String gender;
    
    People(String name){
    	this.name = name;
    }
    People(String name, int age){
    	this.name = name;
        this.age = age;
    }
    People(String name, int age, String gender){
    	this.name = name;
        this.age = age;
        this.gender = gender;
    }
}

People의 생성자를 오버로딩한 예시이다. 메서드의 이름은 People로 모두 갖지만 매개변수의 개수나 타입이 모두 다르다. 오버로딩할 때는 메서드의 이름은 같지만 매개변수의 타입이나 개수를 다르게 구현해야 한다.

오버라이딩 예시

public class People{
	String name;
    int age;
    
	public void eat(){
    	System.out.println("밥을 먹다.");
    };
}

class Woman extends People{
	private String gender;
    
    Woman(String gender){
    	this.gender = gender;
    }
    
    @Override
    public void eat(){
    	System.out.println("고기를 먹다.");
    }
}

Woman 클래스는 People를 상속받았다. 상위 클래스의 메서드인 eat을 하위 클래스인 Woman에서 구현하는 내용을 수정하였다. 따라서 woman.eat()은 "고기를 먹다."를 출력하고 people.eat()은 "밥을 먹다."를 출력한다. 만약 People의 eat 문장도 출력하려면 super 키워드를 사용한다.
@Override는 해당되는 메서드가 오버라이딩된 메서드임을 명시한다.

🎈 장점

객체 중심의 프로그래밍
1. 사람의 관점에서 프로그램을 이해하고 파악
2. 관계는 있지만 없어도 대체해서 동작시킬 수 있는 유연함
3. 재사용성, 확장성, 융통성

🎈 단점

  1. 객체와 클래스를 사용하여 각 모듈의 높은 독립성을 권장하기 때문에 실행 속도 느림
  2. 객체가 많으면 프로그램 용량 증가
  3. 설계에 많은 시간 투자
  4. 설계 실패 시 처음부터 시작
  5. 변수가 존재하고 변수를 통해 객체가 예측할 수 없는 상태를 갖게 되어 버그 발생 가능

🎈 SOLID 설계 원칙

  1. 단일 책임 원칙(SRP)
  2. 개방-폐쇄 원칙(OCP)
  3. 리스코프 치환 원칙(LSP)
  4. 의존 역전 원칙(DIP)
  5. 인터페이스 분리 원칙(ISP)

단일 책임의 원칙(Single Responsibility Principle)

  • 하나의 모듈은 한 가지의 책임을 가져야 한다.
  • 모듈이 변경되는 이유가 한가지여야 한다.
  • 해당되는 모듈이 여러 대상 또는 액터들에 대해 책임을 가져서는 안되고, 오직 하나의 액터에 대해서만 책임을 져야한다.

장점

  • 변경이 필요할 때 수정할 대상이 명확

개방 폐쇄 원칙(Open-Closed Principle)

  • 확장에 대해 열려있고 수정에 대해서는 닫혀야 한다.
  • 확장 : 요구 사항이 변경될 때 새로운 동작을 추가하여 애플리케이션의 기능을 확장 가능
  • 수정 : 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경 가능
  • 추상화에 의존 필요

인터페이스 분리 원칙(Interface Segregation Principle)

  • 목적과 관심이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리 필요
  • 클라이언트의 목적과 용도에 적합한 인터페이스만을 제공하는 것

장점

  • 모든 클라이언트가 자신의 관심에 맞는 퍼블릭 인터페이스만을 접근하여 불필요한 간섭 최소화

리스코프 치환 원칙(Liskov Substitution Principle)

  • 하위 타입은 상위 타입을 대체 가능
  • 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도 차이점을 모른 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용 가능

의존 역전 원칙

  • 고수준 모듈은 저수준 모듈의 구현에 의존하면 안되고, 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 함
  • 고수준 모듈 : 변경이 없는 추상화된 클래스나 인터페이스
  • 저수준 모듈 : 변하기 쉬운 구체 클래스
  • 추상화에 의존하고 구체화는 의존하지 않음

참고

자바 OOP의 4가지 특징과 OOP 5가지 설계 원칙

profile
헐 제가 회사를 다니면서 개발을 하고 있어요 이게 무슨 일이죠?

0개의 댓글