객체지향 프로그래밍

#JAVA #객체지향프로그래밍
Dec 28, 2023
객체지향 프로그래밍
 
객체지향 프로그래밍은 프로그램을 객체 단위로 설계하고 개발하는 패러다임으로써
여기서 "객체"는 데이터와 그 데이터를 조작하는 메서드(함수)의 묶음을 의미하고,
이 객체들은 다른 객체와 상호작용하며 프로그램을 완성시킨다.
상태는 형태를 통해서만 변경 받는다. (캡슐화) 데이터와 함수를 하나의 덩어리(객체)로 묶는 것. 상태를 직접적으로 변경하지 못한다.
 
  1. 클래스와 객체
      • 클래스는 객체를 만들기 위한 템플릿이며, 객체는 클래스의 인스턴스이다.
      • 클래스는 속성(멤버 변수)과 메서드(함수)를 정의하고, 객체는 해당 클래스의 속성과 메서드를 가지게 된다.
  1. 캡슐화(Encapsulation)
      • 데이터와 그 데이터를 다루는 메서드를 하나의 단위로 묶어 캡슐화한다.
      • 이는 정보 은닉(Private)을 통해 객체의 내부 구현을 외부로부터 감추고, 외부에서는 객체의 인터페이스만 접근할 수 있도록 한다.
      💡
      캡슐화 정보 은닉이 목적 (private) > 메소드의 책임을 하나씩 만드는 것. (데이터와 해당 데이터를 조작하는 메서드를 하나의 단위로 묶는 것을 의미)

      캡슐화 예시

      package ex07; interface 행위{ void start(); } class 라면 implements 행위 { private void 물끓이기(){} private void 스프넣기(){} private void 면넣기(){} private void 계란넣기(){} @Override public void start() { //순서를 여기서 정해줌! start만 때리면 이 순서대로 나옴 물끓이기(); 스프넣기(); 면넣기(); 계란넣기(); } } public class ramenTest { public static void main(String[] args) { 라면 ra = new 라면(); ra.start(); //개발자 입장에서 보이는건 start 뿐이니까... } }
       
       
       
       
       
       
       
  1. 추상화(Abstraction)
      • 복잡한 시스템이나 개념을 단순화하고 중요한 요소에 집중하는 것
      • 오브젝트를 추상화 해서 만든다. (상속해서 만든다.)
      • 모두가 부모를 바라보게 만들면 수정할 게 없어서 프로그램 유지·보수에 엄청 편하다.
       
  1. 다형성(Polymorphism)
      • 다형성은 동일한 인터페이스를 통해 다양한 형태의 동작을 지원하는 개념이다.
      • 즉, 한 객체가 여러 가지 타입을 가질 수 있는 능력
      • 동일한 코드가 다양한 객체에 대해 다양한 방식으로 동작할 수 있어서 코드의 유연성과 확장성을 높여준다.
      • 오버로딩(Overloading)과 오버라이딩(Overriding)을 통해 구현된다.
       
  1. 상속(Inheritance)
      • 기존 클래스를 사용하여 새로운 클래스를 만들 수 있는 상속 개념이 있다. (자식 클래스는 부모 클래스의 모든 속성과 동작을 물려받는다.)
      • 상속을 통해 기존 클래스의 특성과 동작을 재사용하고, 새로운 기능을 추가하거나 기존 기능을 수정할 수 있다.
      • 상속을 하려면 다형성을 꼭 지켜야함!
 
이러한 객체지향적 특징들은 코드의 가독성을 높이고, 유지보수가 쉬워지며, 소프트웨어의 재사용성을 증가시킨다.
💡
객체 지향은 ‘상태와 행위’ 모두 들고 있다.
💡
유틸리티 클래스 = 행위만 들고 있는 것. 기능을 수행하는 것. 객체 지향 코드는 아니다.
💡
  • 절차 프로그래밍 —> 데이터와 함수가 분리된다.
    • 데이터와 함수를 하나의 덩어리 묶어서 생각하는 방법이다.
      —> 상태와 행위를 묶어서 생각!
 
  • 객체 프로그래밍 —> 데이터와 함수가 객체로 캡슐화 된다.
    • 데이터와 함수를 하나의 덩어리(객체)로 묶는 것을 캡슐화라고 부른다.
      —> 데이터와 함수가 객체로 캡슐화 된다.
 
  • 객체 프로그래밍 → 핵심은 모든걸 다 부품화 시켜서 결합 할 수 있다!!
    • ex) TV 객체의 경우
      채널번호, 볼륨, 전원상태 등이 상태에 해당
      객체 동작 객체가 취할 수 있는 동작 (기능, 행동)
       
객체 (object) → new 에서 띄울 수 있는게 다 object 이다.
객체 안의 변수를 필드라고 하고
객체 안의 함수를 메서드라고 한다.
 

[ 로버트 마틴의 SOLID ]

notion image

1. 단일 책임 원칙 (SRP)

클래스는 하나의 책임만 가져야한다는 말은, 메서드 하나만 가진다는게 아니다. 청소 / 회계 / 인사 처럼 나눠서, 청소가 잘못되면 청소 담당 메서드의 잘못. 금액이 잘못되면 회계 담당 메서드의 잘못. 이렇게 알기 쉽게 하려고 하는 것. 빗자루 쓸기, 청소기 돌리기. 이런 걸 가진다는게 아니다.

2. 개방-폐쇄 원칙 (OCP)

메서드 재정의해서 동적바인딩 해야 함! 새로운 코드를 만드는 건 OPEN, 기존 코드를 손대는건 CLOSE

3. 리스코프 치환 원칙 (LSP)

오브젝트 같은게 있으면 다운캐스팅 하고 쓰는 그런것... 디자인 패턴 같은걸 공부할 때, 제대로 이해할 수 있다. 지금은 X 서브타입(질럿)은 언제나 기반타입(프로토스)으로 교체할 수 있어야한다.

4. 의존관계 역전 원칙 (DIP)

질럿을 보지말고 프로토스를 봐라 (프로토스에 의존해라)

5. 인터페이스 분리 원칙 (ISP)

인터페이스가 제약하는 행위를 들고 있을 수 있다. (ex. 엑셀, 브레이크 등등) 이런 걸 여러개 만들지 말고, 한 개만 만들라는 말 만약, 행위의 제약을 4개를 시켜야 한다면? 애가 4개를 잘 쓰다가, 이 인터페이스를 다른 클래스에서 사용할때, 2개만 사용하고 싶을 때가 있잖아? 이때 재사용이 안된다!
[ 인터페이스가 제약하는 행위를 2개 들고 있는 경우 ]
package ex17; interface Knife { //2개를 들고있다는게 중요 void kill(); void cook(); } class 백종원 implements Knife { //백종원은... cook만 하는데ㅠㅠ? @Override public void kill() { //kill 안써...ㅠ 이거 만들 필요 없잖아!! 이상한 짓 } @Override public void cook() { System.out.println("요리하다"); } } class 전사 implements Knife { @Override public void kill() { System.out.println("공격"); } @Override public void cook() { System.out.println("요리"); } } public class Hello { }
 
[ 이상한 짓 1 ]
package ex17; interface Knife { //2개를 들고있다는게 중요 void kill(); void cook(); } abstract class 요리사어댑터 implements Knife { //추상클래스라 추상메서드 가질 수 있잖어 오류 안남 //즉, 어댑터는 안쓰는걸 걸러낼 수 있다! //어댇터라는 애가 kill을 구현해버림 > 어댑터 패턴 @Override public void kill() { } } class 백종원 extends 요리사어댑터 { //요리사 어댑터를 상속받은 덕분에 백종원은 cook만 구현해도 됨! @Override public void cook() { System.out.println("요리하다"); } } class 전사 implements Knife { @Override public void kill() { System.out.println("공격"); } @Override public void cook() { System.out.println("요리"); } } public class Hello { }
 
[ 이상한 짓 2 ]
package ex17; interface Knife { //2개를 들고있다는게 중요 default void kill() { //인터페이스 메소드에 defualt를 하면 몸체를 만들 수 있다 (new 문법) //어댑터 패턴 안쓸려고 나옴 } void cook(); } class 백종원 implements Knife { //Knife에서 kill몸체를 구현했으니 cook만 구현하면 된다 @Override public void cook() { System.out.println("요리하다"); } } class 전사 implements Knife { @Override public void kill() { System.out.println("공격"); } @Override public void cook() { System.out.println("요리"); } } public class Hello { }
 
[ ISP를 지킨 코드 ]
저딴 이상한 짓 하지말고 ISP 를 지키기 위해 이렇게 써라!!
package ex17; interface CookAble { void cook(); } interface KnifeAble { void kill(); } class 백종원 implements CookAble { //Knife에서 kill몸체를 구현했으니 cook만 구현하면 된다 @Override public void cook() { System.out.println("요리하다"); } } class 전사 implements CookAble, KnifeAble { @Override public void kill() { System.out.println("공격"); } @Override public void cook() { System.out.println("요리"); } } public class Hello { }
 
 
 
 
 
 
 
Share article

Coding_study