ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL-2024.04.12 - Basic - OOP. 객체지향프로그래밍(OOP)
    > 기초/백그라운드 2024. 4. 12. 17:18

     

     

     

    질문:

    1. OOP 가 뭐야?
    2. 왜 OOP를 사용하는 거야?

     

    1. OOP (Object Oriented Programming) 정의

    - 말 그대로, 객체의 관점에서 프로그래밍하는 것을 의미 (자세히 말하자면 클래스는 설계도고 직접일을 하는 구현체는 인스턴스)

    - OOP는 객체를 기준으로 코드를 나누어 구현하는데, JAVA의 경우 그 구성 부분 단위가 클래스.

     

    // Person 클래스 정의
    public class Person {
        // 필드(속성)
        private String name;
        private int age;
    
        // 생성자
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // 메서드
        public void introduce() {
            System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
        }
    
        // Getter 메서드
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    }
    
    // 객체 생성 및 사용
    public class Main {
        public static void main(String[] args) {
            Person person1 = new Person("Janku", 30);
            person1.introduce(); // "Hello, my name is Janku and I am 30 years old."
    
            System.out.println("Name: " + person1.getName()); // "Name: Janku"
            System.out.println("Age: " + person1.getAge()); // "Age: 30"
        }
    }

     

     

    갑작스러운 JAVA예제이지만,  위의 예제를 살펴보면, 

     

    1) Person  Class 정의

    • Person 클래스는 nameage라는 private 필드 가짐.
    • Person 클래스의 생성자 Person(String name, int age)는 객체를 초기화할 때 nameage를 설정.
    • introduce() 메서드는 객체의 정보를 출력.
    • getName()과 getAge() 메서드는 private 필드인 name과 age의 값을 외부에서 읽을 수 있게함.

    2) 객체 생성 및 사용

    • Main 클래스의 main 메서드에서 Person 클래스의 인스턴스인 person1 객체를 생성.
      > 이때, 생성자를 호출하여 name을 "John", age를 30으로 초기화.
    • person1.introduce()를 호출해 Hello, my name is John and I am 30 years old."라는 메시지가 출력.
    • person1.getName()과 person1.getAge()를 통해 name과 age의 값을 각각 "John"과 30으로 출력합니다.

     

     

    2. OOP 사용 이유

    - 기존 C 언어들은 절차 지향

    - 절차 지향으로  해당 코드를 다시 작성하면, 아래와 같음

     

    // Person 클래스의 필드(속성)
    private static String name;
    private static int age;
    
    // Person 객체 생성 및 사용
    public class Main {
        public static void main(String[] args) {
            // Person 객체의 필드 초기화
            name = "John";
            age = 30;
    
            // introduce() 메서드 호출
            introduce(); // "Hello, my name is John and I am 30 years old."
    
            // getName()과 getAge() 함수 호출하여 정보 출력
            System.out.println("Name: " + getName()); // "Name: John"
            System.out.println("Age: " + getAge()); // "Age: 30"
        }
    
        // introduce() 함수 정의
        public static void introduce() {
            System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
        }
    
        // getName() 함수 정의
        public static String getName() {
            return name;
        }
    
        // getAge() 함수 정의
        public static int getAge() {
            return age;
        }
    }

     

     

    - 위의 코드와 같이 절차지향 프로그래밍으로 작성한 경우, 컴파일이나 런타임에 문제는 없음. 

    - 만약 다른 사람을 넣고 싶으면? (100명 정도) >  사람에 따라 새롭게 작성을 해줘야함 * 100.

    - 만약 100명 넣은 코드를 바꿔야하면 ? > 새롭게 작성된 코드를 바꿔야함 * 100

    - 이 말은, 해당 코드는 재사용이 불가 & 유지 보수 최악 의미.

    - OOP를 사용하면, 이런 행위를 최소한으로 할 수 있음

     

    ... 생략 ...
    
    Person person1 = new Person("Janku", 30);
    person1.introduce(); // "Hello, my name is Janku and I am 30 years old."
    
    Person person2 = new Person("Jason", 12);
    person1.introduce(); // "Hello, my name is Jason and I am 12 years old."
    
    
    ... 생략 ...

     

     

     

    3. OOP 특징

     

    1) 캡슐화, Encapsulation : 객체의 데이터와 메서드를 묶음 (데이터와 메서드를 객체 하나로 묶고, 외부에서 직접 접근을 제어)

    - 캡슐화는 데이터와 그 데이터를 처리하는 메서드를 하나로 묶음

    - 이를 통해 객체의 내부 구현을 외부로부터 감추고 객체 간의 상호 작용은 정의된 인터페이스를 통해서만 가능.

    public class Person {
        private String name;
        private int age;
    
        // 생성자
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        // Getter 메서드
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    
        // Setter 메서드 (내부 데이터 변경을 허용하는 경우)
        public void setAge(int age) {
            if (age >= 0) {
                this.age = age;
            }
        }
    }
    
    // 위의 예제에서 Person 클래스는 name과 age라는 필드를 private으로 선언하여 외부에서 직접 접근 불가
    // 대신에 getName()과 getAge() 메서드를 통해 외부에서 필드 값을 읽음. 
    // 이렇게 하면 내부 데이터에 대한 접근을 제어하고, 데이터 유효성을 보장.

     

     

     

    2) 은닉화, Information hiding : 필요한 녀석만 보기

    - 은닉화는 캡슐화의 목표로, 객체의 내부 구현 세부 사항을 외부로부터 숨기는 것을 의미.

    - 객체의 내부 상태는 private으로 선언하고, 외부에서 접근 가능한 메서드를 통해 데이터에 접근.

     

    public class BankAccount {
        private double balance; // 은행 계좌 잔액
    
        // 입금 메서드
        public void deposit(double amount) {
            if (amount > 0) {
                balance += amount;
            }
        }
    
        // 출금 메서드
        public void withdraw(double amount) {
            if (amount > 0 && balance >= amount) {
                balance -= amount;
            }
        }
    
        // 잔액 조회 메서드
        public double getBalance() {
            return balance;
        }
    }
    
    // 위의 예제에서 BankAccount 클래스는 balance 필드를 private으로 선언하여 외부에서 직접 접근 불가. 
    // 대신에 deposit(), withdraw(), getBalance() 메서드를 통해 입금, 출금, 잔액 조회 기능을 제공. 
    // 이렇게 하면 잔액을 직접 조작하는 것을 외부로부터 숨김.

     

     

     

     

    3) 상속, Inheritance : 재정의

    - 상속은 기존 클래스(부모 클래스)의 속성과 메서드를 그대로 물려받아 새로운 클래스(자식 클래스)를 생성.

    - 자식 클래스는 부모 클래스의 기능을 확장하거나 수정하여 재사용.

    public class Animal {
        public void makeSound() {
            System.out.println("Animal sound");
        }
    }
    
    public class Dog extends Animal {
        @Override
        public void makeSound() {
            System.out.println("Bark bark!");
        }
    }
    
    // 위의 예제에서 Animal 클래스는 makeSound() 메서드 지님. 
    // Dog 클래스는 Animal 클래스를 상속받았으며, makeSound() 메서드를 재정의하여 "Bark bark!"를 출력.

     

     

     

    4) 추상화, Abstraction: 공통된 속성이나 기능을 묶음 (현실 세계의 개념을 간추려서 모델링하고 클래스로 표현)

    - 추상화는 공통의 속성이나 기능을 묶어 이름을 붙이는 것을 의미.

    - 추상화를 통해 객체의 중요한 특징에만 초점을 맞추고 불필요한 세부 사항을 숨김.

     

    public abstract class Shape {
        public abstract double calculateArea();
    }
    
    public class Circle extends Shape {
        private double radius;
    
        public Circle(double radius) {
            this.radius = radius;
        }
    
        @Override
        public double calculateArea() {
            return Math.PI * radius * radius;
        }
    }
    
    // 위의 예제에서 Shape 클래스는 도형의 추상적인 개념을 나타내며, calculateArea() 메서드를 추상 메서드로 선언. 
    // Circle 클래스는 Shape 클래스를 상속받아 원의 면적을 구하는 기능을 구현.

     

     

     

     

    5) 다형성, Polymorphism: 딴말하기 (Overload & Override)

    - 다형성은 같은 이름의 메서드가 서로 다른 클래스에서 다르게 동작.

    - 다형성을 통해 코드의 유연성과 재사용성을 높임.

     

    public class Animal {
        public void makeSound() {
            System.out.println("Animal sound");
        }
    }
    
    public class Dog extends Animal {
        @Override
        public void makeSound() {
            System.out.println("Bark bark!");
        }
    }
    
    public class Cat extends Animal {
        @Override
        public void makeSound() {
            System.out.println("Meow!");
        }
    }
    
    // 위의 예제에서 Animal 클래스의 makeSound() 메서드는 Dog 클래스와 Cat 클래스에서 각각 다르게 재정의되어 동작. 
    // 이렇게 하면 동일한 메서드 이름으로 다양한 객체를 처리 가능

     

     

    답변

    1. OOP 가 뭐야?
      - OOP는 객체지향-프로그래밍으로 현실 세계를 추상화하여 데이터와 해당 데이터를 처리하는 메서드를 하나의 객체로 묶은 기법
      - 좀 더 쉽게, 객체 위주로 (객체를 만들어) 코드를 짜는 기법

    2. 왜 OOP를 사용하는 거야?
      - 조금 복잡하더라도, 한번 제대로 짜두면 높은 재사용성과 유지보수 측면에서 이득 !

     

     

     

    댓글

Designed by Tistory.