[F-Lab 66해빗 페이백 챌린지 ]

[F-Lab 모각코 챌린지 2일차] 객체는 무엇이고 객체 지향 프로그래밍은 무엇인가? (4가지 특성)

everydeveloper 2023. 5. 10. 23:39

오늘 학습 계획

  • 자바의 신 2권 19 -21 chapter 읽기 (19장 학습)
  • 코칭팀 ‘나의 대답은?’ 세션 답변하면서 학습

TIL

  • 컴퓨터가 2진법을 사용하는 이유
  • 표현범위에서 양수가 -1표현범위를 갖는 이유 - (2의 보수법의 경우 학습)
  • CPU가 I/O 작업의 요청이 있을때 처리하는 방법
  • JRE와 JDK의 차이 (자바의 신)
  • 자바 버전 별 변화점 (자바의 신)
  • GC와 JVM부분 복습 (자바의 신)
  • 객체지향 프로그래밍에 관해 학습 진행중
    • 객체란 무엇이며 객체지향 프로그래밍은 무엇인가?
    • 상속
    • 다형성
    • 캡슐화
    • 절차지향적 프로그래밍과 차이점

 

객체란?

객체는 현실 세계의 사물이나 개념을 프로그래밍에서 사용할 수 있는 데이터와 동작(메소드)을 포함하는 소프트웨어 구성 요소입니다.

객체는 속성(attribute)과 동작(method)으로 구성되어 있으며, 이러한 객체들이 상호작용하면서 프로그램이 실행됩니다.

 

객체지향 프로그래밍

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그래밍 패러다임 중 하나로, 객체를 중심으로 프로그램을 설계하고 구현하는 방식입니다. 객체지향 프로그래밍은 다음과 같은 특징을 갖고 있습니다

 

4가지 특징

  • 캡슐화(Encapsulation): 객체의 속성(데이터)과 동작(메소드)을 하나의 단위로 묶는 것을 의미합니다. 캡슐화를 통해 객체의 내부 구현을 외부로부터 숨기고, 객체 간의 상호작용은 메소드를 통해서만 이루어지게 합니다. 이를 통해 코드의 유지 보수와 확장성이 증가합니다.
  • 상속(Inheritance): 기존 클래스의 속성과 동작을 다른 클래스가 물려받는 기능입니다. 이를 통해 코드의 중복을 줄이고, 재사용성을 높입니다.
  • 다형성(Polymorphism): 하나의 인터페이스나 부모 클래스를 통해 여러 가지 타입의 객체를 다룰 수 있는 기능입니다. 다형성을 통해 코드의 유연성과 확장성을 증가시킬 수 있습니다.
  • 추상화(Abstraction): 복잡한 시스템을 좀 더 간결하고 이해하기 쉽게 단순화시키는 과정입니다. 프로그램에서 중요한 정보와 기능만을 표현하고, 불필요한 세부 사항은 숨김으로써 전체적인 구조를 파악하기 쉽게 만듭니다.

그리고 자바로 객체지향을 지원하는 언어라고 해서

코딩을 하면 무조건 객체지향 프로그래밍 되는 건 아니고 절차지향적 프로그래밍도 가능하다.

즉 객체지향 프로그램밍이 먼지 알고 있어야 자바를 제대로 활용 할 수 있고 객체지향적 프로그래밍을 할 수 있다.

그리고 지금은 객체지향적 프로그래밍이 대세고 많이 채택되고 있지만 이것도 하나의 철학이자 패러다임이여서

시대나 기술이 변하면 언제든지 다른 패러다임으로 대체 될 수 있다.

객체지향은 한사람이 고안해 낸게 아니라 여러 사람들의 노력과 연구를 통해 점진적으로 발전하고 정립된 개념이라 당분간은

많이 사용 되겠다는 생각이 들었다.

그리고 위의 4가지 특징이 있는데 4가지를 다 써야 객체지향적 프로그래밍이라고 부를 수 있는 것은 아니고 3개나 2개 등을 써도 그렇게 부를 수 있다. 이건 특징이자 패러다임이라 많이 쓸 수록 객체지향적이라고 할 수 있겠다.

캡슐화와 모듈화

캡슐화와 모듈화라는 개념이 나의 경우 햇갈렸다.

 

내가 보기 엔 둘 다 개방적이지 않고 폐쇄적인 느낌에 코드를 한 군데에 모아서 관리 및 유지보수성을 올리는 느낌을 받았기 때문이다.

모듈화를 다시 찾아보니

모듈화(Modularity)는 큰 프로그램을 작은 독립적인 모듈로 나누는 것입니다. 각 모듈은 독립적으로 작동하며, 다른 모듈과의 상호 작용을 통해 전체 시스템이 구성됩니다. 모듈화는 소프트웨어 개발을 쉽게 관리할 수 있도록 하고, 재사용성을 높여 개발 시간과 노력을 줄일 수 있습니다.

 

위의 정보들을 종합해서 정리보니 두개는 먼가 관련 있어 보이는 느낌을 받는데 서로 다른 목적을 가지고 있다고 하였다.

캡슐화의 정의는 객체의 동작과 속성을 하나의 단위로 묶는 것이고

모듈화는 코드를 기능별로 나누어 독립적인 모듈로 구성하는 것을 의미한다.

잘 생각해보면

모듈화는 큰 것 -> 작은 것 여러개로 나누는 것

캡슐화는 객체의 속성과 동작을 하나의 단위로 묶는 것이다.

 

모듈화를 하면서 캡슐화를 이용 할 수 있는 것이고 꼭 이용해야 하는 것도 아니다.

하지만 둘다 객체지향 특징을 보여주는 것으로 둘 다 적용하면 더욱 객체지향 프로그래밍다워질 것이다.

 

멘토님께서 예시 코드를 보면 더욱 이해하기 좋을 것이라고 하셔서 한번 CHATGTP에게 물어보았다.

 

캡슐화 자바 코드 예시

public class BankAccount {
    // Private 속성으로 캡슐화 적용
    private double balance;

    // 생성자(Constructor)
    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // 입금 메소드(Deposit)
    public void deposit(double amount) {
        balance += amount;
    }

    // 출금 메소드(Withdraw)
    public void withdraw(double amount) {
        if (balance >= amount) {
            balance -= amount;
        } else {
            System.out.println("Insufficient funds!");
        }
    }

    // 잔액 확인 메소드(Get Balance)
    public double getBalance() {
        return balance;
    }
}

이 코드에서 BankAccount 클래스의 balance 속성은 
private로 선언되어 있어 외부에서 직접 접근할 수 없습니다. 
이를 통해 balance에 대한 변경이나 조회는 메소드를 통해서만 가능하며, 이를 통해 데이터의 무결성을 보장합니다. 
이러한 접근 방식이 캡슐화의 예시입니다.

 

일단 기본적으로 속성에 해당하는 double 타입 balance 변수가 있고

입금, 출금 메소드가 있다. 한 클래스 안에 묶어져 있어서 한 단위로 볼 수 잇겠고

외부에서는 이 메소드를 통해 변수값을 조절 할 수 있다.

외부는 이 클래스를 몰라도 이 메소드를 호출 하여 사용한다면 balance 변수값을 조절할 수 있다.

이 것이 캡슐화의 예시이다.

 

모듈화 코드 예시

모듈화는 코드를 기능별로 나누어 독립적인 모듈로 구성하는 것을 의미합니다. 
여기에는 클래스, 패키지 등이 포함됩니다. 아래 예제는 간단한 모듈화를 적용한 자바 코드입니다.

예를 들어, 우리는 도형의 면적을 계산하는 프로그램을 만들고자 합니다. 
이때 모듈화를 사용하면 다음과 같이 작성할 수 있습니다.

먼저, 도형의 공통적인 속성과 메소드를 가진 추상 클래스 Shape를 만듭니다.

Shape.java:

public abstract class Shape {
    public abstract double getArea();
}
다음으로, Shape 클래스를 상속받아 원(Circle)과 사각형(Rectangle) 클래스를 구현합니다.

Circle.java:

public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Rectangle.java:

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 getArea() {
        return width * height;
    }
}
마지막으로, 메인 클래스에서 원과 사각형의 면적을 계산합니다.

Main.java:

public class Main {
    public static void main(String[] args) {
        Circle circle = new Circle(5);
        Rectangle rectangle = new Rectangle(4, 6);

        System.out.println("Circle area: " + circle.getArea());
        System.out.println("Rectangle area: " + rectangle.getArea());
    }
}
이 예제에서는 도형의 면적을 계산하는 기능을 Shape, Circle, Rectangle 클래스로 나누어 모듈화했습니다. 
이렇게 코드를 모듈화하면 각 기능별로 독립적으로 작성하고 테스트할 수 있으며, 
코드의 가독성과 재사용성이 향상됩니다.


참조: chatgtp

 

이거는 원면적과 사각형의 면적을 구하는 건데

하나의 클래스 안에서 구현을 다 할 수도 있는데

CIrcle, Rectangle 클래스로 나뉘고

각 클래스의 메소드를 main클래스에 호출하는 방법으로 모듈화를 진행한 것이다.

이렇게 코드를 더 작은 부분으로 나누면

당장에 시각적으로 보더라도 CIrcle 면적 구하는 부분, Rectangle 면적 구하는 부분이 바로 보이고

어떤 부분이 에러가 나면(에러가 Rectangle과 관련해서 발생했다고 가정한다면)

Rectangle 클래스 부분을 수정 하면 된다.

즉 소스를 분석하기도 쉽고,

유지보수도  상대적으로 쉽다는 이야기이다.

 

상속과 다형성

 

그리고 상속과 다형성에 대해 개념이 헷갈려서 좀 더 알아보았다.

다형성이 있으려면 상속이 있어야한다.

상속이 먼저 진행 되어야만 다형성이 있을 수 있다는 이야기이다.

상속이 된 후 오버라이드 등을 이용해서 다양한 파생메소드 등을 만들 수 있다.

상속과 다형성은 완전 다른 개념이지만

다형성의 특징상 상속이 먼저 진행된다는 전제가 필요하다.

다형성은 나의 인터페이스나 부모 클래스를 통해 여러 가지 타입의 객체를 다룰 수 있는 기능입니다. 

인터페이스는 implement(상속의 한 종류)을 진행 한 후 구현 할 수 있고, 부모 클래스도 extend(상속의 한 종류)를 진행하여만 부를 수 있는 클래스간의 관계명이기 때문이다.

다형성은 상속 한 후 그 것을 제대로 구현하거나, 활용 한다고 상속의 본래의 최종 목적이라 할 수 있는 것 같다(나의 생각)

상속만 하면 인터페이스나, 부모클래스를 복제하는 거나 다름이 없다고 생각이된다.

하지만 상속 한 뒤 구현/활용/변형을 하면 예기가 달라진다.

상속 한 클래스 /  상속 받은 클래스 간의 관계가 생긴다. 즉 원본 클래스 / 활용 클래스, 인터페이스 / 구현클래스 같은 관계가 형성이 된다.

많이 쓰이지는 않은 것 같지만 이론으로만 보면 다양한 Variation이 가능한 것 같다.