객체지향이란?

허준기·2023년 4월 21일
1

자바

목록 보기
2/9

객체지향(Object Oriented)

 실제 세계를 모델링하여 소프트웨어를 개발하는 방법으로서,
 객체지향 프로그래밍에서는 데이터와 절차를 하나의 덩어리로 묶어서 생각한다. 

코드를 작성하는 방법 중 하나

장점

  1. 재사용성
  2. : 상속을 통해 코드의 재사용 가능
  3. 생산성 향상
  4. : 클래스를 만들어 독립적인 객체를 사용함으로써 개발의 생산성 향상
  5. 자연적인 모델링
  6. : 일상생활의 구조가 객체에 녹아들어 있기 때문에 생각하고 있는 것을 그대로 자연스럽게 구현 가능
  7. 유지보수
  8. : 프로그램 추가, 수정이 용이

절차지향(Procedural Programming)

 
물이 위에서 아래로 흐르는 것처럼 순차적인 처리가 중요시되며 프로그램 전체가 유기적으로 연결되도록 만드는 프로그래밍 기법

대표적으로 C언어가 있다

장점

  • 컴퓨터의 처리구조와 유사해 실행 속도가 빠름

단점

  • 유지보수가 어려움
  • 디버깅이 어려움
  • 실행순서가 정해져 있으므로 코드의 순서가 바뀌면 동일한 결과를 보장하기 어려움

객체지향과 절차지향의 차이

절차 지향은 데이터를 중심으로 함수를 구현하고,
객체 지향은 기능을 중심으로 메소드를 구현한다.

절차 지향은 실행 순서,절차가 더 중점이 되고,
객체 지향은 필요한 객체들의 종류와 속성 등이 더 중점이 된다.

절차 지향의 반대는 객체지향이 아니고, 객체지향의 반대는 절차지향이 아니다!!!!!!!
더 나은 방법은 없고, 성격에 따라 다를 뿐이다

클래스(Class)

 객체지향 프로그래밍에서 특정객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀
 객체를 정의하기 위한 메소드와 필드(변수)로 구성
 자바에서 모든 코드는 반드시 클래스 안에 존재해야 하며
 서로 관련된 코드들을 그룹으로 나누어 별도의 클래스 구성
 
public class Car {
   int speed = 0;
   String name;
   String color;

   void information(){
       System.out.println(name);
       System.out.println(color);
   }
   void move(){
       System.out.println(name + " move");
   }

   void speedUp(){
       speed += 10;
   }

   void speedDown(){
       speed -= 10;
   }

   void stop(){
       speed = 0;
       System.out.println(name + " stop");
   }

} 

Car라는 클래스를 만들어봤다. 이 클래스는 기본적으로 speed, name, color 이라는 필드를 가지고 있고 information(), move(), speedUp(), speedDown(), stop() 이라는 메서드를 가지고 있다.

인스턴스

 메모리에 할당된 객체 

하나의 클래스로부터 여러 개의 인스턴스를 생성할 수 있는데 이렇게 생성된 인스턴스는 독립된 메모리 공간에 저장된 자신만의 필드를 가질 수 있다.

객체

 클래스에서 정의한 것을 토대로, 메모리(실제 저장공간)에 할당된 것으로
 프로그램에서 사용되는 데이터 또는 식별자에 의해 참조되는 공간을 의미하며,
 변수, 자료구조, 함수 또는 메소드가 될 수 있다.

모든 실재하는 대상을 객체라고 볼 수 있다.

객체와 인스턴스는 얼핏 보면 같은 개념인줄 알 수 있지만 약간 다르다.
객체는 우리가 클래스로 구현할 어떤 것이라고 할 수 있다.
인스턴스는 그 객체를 실체화 시킨 것이다.

위에 만들어놓은 Car 클래스를 사용하기 위해서는 객체를 생성해 주어야 한다.
Car nicecar = new Car();
nicecar라는 객체를 만들었다 → 인스턴스화

메소드

 어떠한 특정 작업을 수행하기 위한 명령문의 집합 
 클래스의 기능(동작)에 해당하는 구현 부분으로
 해당 메소드 호출 시 메소드의 블럭({})에 해당하는 부분 실행
   void information(){
       System.out.println(name);
       System.out.println(color);
   }
   void move(){
   	speed += 10;
       System.out.println(name + " move");
   }

   void speedUp(){
       speed += 10;
   }

   void speedDown(){
       speed -= 10;
   }

   void stop(){
       speed = 0;
       System.out.println(name + " stop");
   }

위의 코드에는 information(), move(), speedUp(), speedDown(), stop() 라는 5개의 메서드를 만들어 놓았다.

  • `information()` 메소드는 자동차의 이름과 색깔을 출력해준다
  • `move()` 메소드는 `speed` 를 10 올려주고 자동차의 이름과 move를 출력해준다
  • `speedUp()` 메소드는 자동차의 `speed`를 10 올려준다
  • `speedDown()` 메소드는 자동차의 `speed`를 10 내려준다
  • `stop()` 메소드는 자동차의 `speed`를 0으로 만들고 자동차의 이름과 stop를 출력해준다

특성

객체 지향적 설계를 통해 소프트웨어를 개발하면 코드의 재사용을 통해반복적인 코드를 최소화하고, 보다 유연하고 변경이 용이한 프로그램을 만들 수 있다. → 이러한 특징들은 객체 지향 프로그래밍의 4가지 특성에서 오는 것인데, 지금부터 한번 알아보자!!!

추상화(Abstration)

 실제 세상을 객체화하는게 아니라 필요한 정보만을 중심으로 간소화하는것.
 객체의 공통적인 속성과 기능을 추출하여 정의하는것.
 
public interface Vehicle {
   public abstract void information();
   public abstract void move();
   public abstract void speedUp();
   public abstract void speedDown();
   void stop();
}

위의 코드를 보면 public abstract 라는 코드가 있는데 추상메소드를 선언하는 코드다
Vehicle이라는 인터페이스를 만들어서 탈것의 공통적인 기능을 추상메소드로 만들어줬다.

public class Car implements Vehicle {
    int speed = 0;
    String name;
    String color;
    int wheels = 4;

    public void information() {
        System.out.println(name + "Car");
        System.out.println("Color : " + color);
        System.out.println("Wheels : " + wheels);
    }

    public void move() {
        speed += 10;
        System.out.println(name + " move");
    }

    public void speedUp() {
        speed += 10;
    }

    public void speedDown() {
        speed -= 10;
    }

    public void stop() {
        speed = 0;
        System.out.println(name + " stop");
    }

}

Vehicle 인터페이스를 받은 Car클래스

public class Motorcycle implements Vehicle {
    int speed = 0;
    String name;
    String color;
    int wheels = 2;

    public void information() {
        System.out.println(name + " Motorcycle");
        System.out.println("Color : " + color);
        System.out.println("Wheel : " + wheels);
    }

    public void move() {
        speed += 10;
        System.out.println(name + " move");
    }

    public void speedUp() {
        speed += 10;
    }

    public void speedDown() {
        speed -= 10;
    }

    public void stop() {
        speed = 0;
        System.out.println(name + " stop");
    }
}

Vehicle 인터페이스를 받은 Motorcycle클래스

CarMotorcycle 클래스 둘다 Vehicle인터페이스에 있는 추상 메소드 들을 구현해주었다.

추상 메소드(Abstract Method)

 자식 클래스에서 오버라이딩해야만 사용할 수 있는 메소드
자바에서 추상 메소드를 사용하는 목적은 추상 메소드가 포함된 클래스를 
상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함
abstract 반환타입 메소드이름();

캡슐화

 
 추상화를 통해 객체를 정의했다면, 
 객체에 필요한 데이터나 기능(메소드)을 책임이 있는 객체에 그룹화 시켜 주는것
 
 객체에 직접적인 접근을 막고 외부에서 내부의 정보에 직접접근하거나 변경할 수 없고, 
 객체가 제공하는 필드와 메소드를 통해서만 접근가능
 

정보은닉

캡슐화의 가장 큰 장점

 외부에서 객체접근하는데 있어서 정보를 숨기고 객체의 연산을 통해서만 접근이 가능하게 하는 것
 
  • 외부에서 특정 객체의 데이터 및 함수의 직접 접근을 막음으로써 변경하지 못하게 한다
  • 유지보수나 확장시 오류의 범위를 최소화
  • 객체내 정보손상, 오용을 방지
  • 조작법이 바뀌어도 사용방법 자체는 바뀌지 않음
  • 데이터가 변경되어도 다른 객체에 영향을 주지 않기 때문에 독립성이 좋음
  • 처리된 결과사용으로 이식성이 좋음
  • 객체를 모듈화 할 수 있어 새로운 시스템의 구성에 하나의 모듈처럼 사용 가능

접근제어자

캡슐화를 하기 위해서는 접근제어자를 통한 설계가 잘 이루어져야 한다.
자신 내부의 모듈은 감추고, 다른 모듈의 내부 작업도 직접적으로 개입하지 못하도록 설계해야한다.

접근제어자에 대한 내용은 아래에 정리하거나 따로 글을 쓸 예정이다

상속

 상위 클래스의 기능을 하위 클래스가 사용할 수 있는 개념.
 상쇽이 필요한 이유는 여러 객체에서 사용되는 기능을 하나의 클래스로 분리해서 사용할 수 있도록 위함이다
 → 중복되는 코드의 재사용성을 위함
 
 기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소
 

위에서 구현한 CarMotorcycle 클래스에서 Vehicle인터페이스에서 추상메소드로 선언한 information(), move(), speedUp(), speedDown(), stop() 들을 구현해줬는데 두개의 클래스에서의 메소드 내용이 겹친다.
그리고 speed, name, color, wheel이라는 필드들도 겹친다.
이를 해결해주기 위해 Vehicle2라는 클래스를 만들어 상속을 통해 문제를 해결해보겠다!

부모 클래스

Vehicle2라는 부모 클래스를 만들어보자

public class Vehicle2 {
   int speed = 0;
   String name;
   String color;
   int wheels;

   public void information() {
       System.out.println(name + "Car");
       System.out.println("Color : " + color);
       System.out.println("Wheels : " + wheels);
   }

   public void move() {
       speed += 10;
       System.out.println(name + " move");
   }

   public void speedUp() {
       speed += 10;
   }

   public void speedDown() {
       speed -= 10;
   }

   public void stop() {
       speed = 0;
       System.out.println(name + " stop");
   }
}

Car클래스와 Motorcycle 클래스와 별로 다를건 없어보인다. 두 클래스의 공통된 부분을 합쳐서 만들어줬다.

자식 클래스

이제 Vehicle클래스를 상속받아 Car 클래스와 Motorcycle클래스를 바꿔보자

Car 클래스

public class Car extends Vehicle2 {
   int wheels = 4;

   public void openWindow(){
       System.out.println("창문을 활짝 엽니다");
   }

   @Override
   public void information(){
       System.out.println("Name : " + name);
       System.out.println("Color : " + color);
       System.out.println("Wheels : " + wheels);
   }
}

extends명령어를 통해 부모클래스인 Vehicle2를 상속받았다.
부모클래스에 이미 정의되어있는것들을 다시 써줄 필요가 없어 재사용성이 좋다.
openWindow()라는 메소드를 새로 만들어줬는데 이 메소드는 부모클래스인 Vehicle2에서는 사용할 수 없는 확장된 메소드이다

Motorcycle 클래스

public class Motorcycle extends Vehicle2 {
   int wheels = 2;

   public void stunt(){
       System.out.println("바이크가 묘기를 부립니다!");
   }

   @Override
   public void speedUp(){
       speed += 15;
   }

   @Override
   public void information(){
       System.out.println("Name : " + name);
       System.out.println("Color : " + color);
       System.out.println("Wheels : " + wheels);
   }
}

Motorcyle클래스도 Vehicle2클래스를 상속받았다.
@Override를 통해 speedUp()메소드를 재정의 해줬다.
부모클래스인 Vehicle2speed를 10씩 올리는 반면에 재정의를 통해 speed를 15씩 올리게 해줬다.

다음은 Car클래스와 Motorcycle클래스의 객체를 생성해서 각각 동작해본 코드다

public class Control {
   public static void main(String[] args){
       Car nicecar = new Car();
       Motorcycle goodmotorcycle = new Motorcycle();

       nicecar.name = "nicecar";
       nicecar.color = "purple";

       goodmotorcycle.name = "goodmotorcycle";
       goodmotorcycle.color = "black";

       nicecar.information();
       goodmotorcycle.information();

       nicecar.openWindow();
       goodmotorcycle.stunt();

       nicecar.move();
       goodmotorcycle.move();
       nicecar.speedUp();
       goodmotorcycle.speedUp();
       nicecar.printSpeed();
       goodmotorcycle.printSpeed();
   }
}

해당 코드의 결과는 이렇게 나온다

다형성

 하나의 객체나 메소드가 여러가지 다른 형태를 가질 수 있는 성질
 

장점

  • 유지보수가 쉬움
  • 재사용성 증가
  • 느슨한 결합

다형성 필수 조건

  • 상속 관계
  • 오버라이딩 필수
  • 업캐스팅

다형성은 조사할게 많아보이니까 나중에 따로 글써서 정리해야겠당

피드백 환영해요

profile
나는 허준기

0개의 댓글