Software Architect

[OOAD] 캡슐화, 상속, 다형성, Interface 등

이반&핫버드 2022. 3. 21. 21:21

캡슐화

캡슐

  • 데이터, 필드 
  • 허용하는 데이터/필드로만, 데이터 제어 가능
  • 허용하지 않는 데이터/필드 접근 막음 >> 은닉

 

캡슐화 장점

  • Server code가 허용한 방법대로 Client code를 작성하도록 유도

 

코드 적용 예

package com.company;

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello");

        GameMachine gm = new GameMachine();
        gm.inputCoin(5);
        gm.playGame();
        gm.currentStatus();

    }
}

class GameMachine{
    private int totalCoin = 0;        // [1] //

    public void inputCoin(int a) {
        if (a > 10 || a < -10) {      // [2] //
            System.out.println("Error!! Coin is too big");
            return;
        }

        if (a + totalCoin > 5) {
            System.out.println("Error!! Max");
        }
        totalCoin += a;
    }

    public void playGame(){
        totalCoin -= 1;
    }

    public void currentStatus() {
        System.out.println(totalCoin);
    }
}
  • [1] private로 접근하지 못하도록 막아둠
  • [2] Client에서 어떻게 사용해도 버그가 발생하지 않도록 처리

 


 

상속

개요

  • 상속 : 부모가 가진 요소드를 자식이 물려받아 사용
  • OOP 상속
    : 부모/자식 관계로 보기 어려움
    : 코드 중복 방지를 위해 공통적인 요소를 일반화 시킴 
      >> 중복된 메서드/필드 = 변경 시 모두 수정 필요 -> 버그 유발

코드 적용 예

package com.company;

public class Main {
    public static void main(String[] args) {
        SpeedRobot spr = new SpeedRobot();
        spr.stop();
        //spr.run();

        SmartRobot smr = new SmartRobot();
        smr.stop();
        smr.sitDown();
    }
}

class Robot {
    int hp;
    void stop() { System.out.println("Parent-Stop"); }   // [1] //
    void move() { System.out.println("Parent-Move"); }
}

class SpeedRobot extends Robot {                         // [2] //
    int modelID;

    void stop() { System.out.print("Re-Stop"); }

    void run () { System.out.print("Run"); }
    void Walk() { System.out.print("Walk"); }
}

class PowerRobot extends Robot {
    int mana;

    void attack() { System.out.print("Attack"); }
    void jump  () { System.out.print("Jump"  ); }
}

class SmartRobot extends Robot{
    int IQ;
    void fly() { System.out.print("Fly"); }
    void sitDown() { System.out.print("SitDown"); }
    void StandUp() { System.out.print("StandUp"); }
}
  • [1] 중복 되는 부분을 Class로 작성
  • [2] 중복 되는 Class 부분을 사용하는 Class 사용 = extends
  • Super Class / Derived Class (분류/파생)
    Base Class / Sub Class       (기원/종류)

 

객체와 분류 관계

  • "is a" 관계
  • "is a kind of" 관계
  • 객체와 분류

 

 

Overloading / Overriding

  • Overriding = Suppler Class 메서드 재정의
  • Overloading = 동일한 이름의 메서드, 다른 Argument로 함수 구분

 

코드 적용 예

public class SpeedRobot extends Robot {
    int modelID = 10;
    
    void move() { System.out.println("Fast run"); }           // [1] //
    void move(int i) { System.out.println("run =" + i); }     // [2] //
    
    void run() {}
    void walk() {}
}
  • Super class인 Robot Class의 move()를 다시 정의 -> Overriding
  • [1], [2]와 같이 동일한 이름, 다른 argument의 메서드

 


다형성

개요

  • 다형성 = 한 객체가 다양한 타입을 담을 수 있는 형태
  • 상속관계 구현하여 다형성 적용

 

코드 적용 예

package com.company;

public class Main {
    public static void main(String[] args) {
        Rifle rf = new Snifer();
        rf.shot();

        rf = new Shotgun();
        rf.shot();
    }
}

class Rifle {
    void shot() { System.out.println("RIFLE"); }    // [1] //
}

class Shotgun extends Rifle {
    void shot() { System.out.println("SHOTGUN"); }  // [2] //
}

class Snifer extends Rifle {
    void shot() { System.out.println("SNIPER"); }   // [3] //
}
  • Super Class의 메서드 [1]을 Deriverd Class의 메서드 [2]를 재정의

 


Interface

개요

  • 내부에 접근하기 위한 공통적 형태
  • 사용자는 Interface만 알고 있으면 쉽게 함수 사용 가능

 

Interface 사용하는 이유

  • 확장 가능한 형태 
  • 객체를 쉽게 사용하고자 표준화 시킴

 

코드 적용 예

package com.company;

public class Main {
    static Socket factory(String name) {
        if (name == "Dansang")  return new Dansang();
        if (name == "Samsang")  return new Samsang();
        if (name == "SunPower") return new SunPower();
        return null;
    }
    static void TVShow(Socket s) {
        s.plugin();
        System.out.println("Watching TV");
    }

    public static void main(String[] args) {
        TVShow(new Dansang());

        Socket s = factory("Samsang");
        TVShow(s);

        TVShow(factory("SunPower"));
    }
}

interface Socket {                  // [1] //
    void plugin();
    void unplugin();
}

class Samsang implements Socket {
    @Override                       // [2] //
    public void plugin() { System.out.println("Plugin-Samsang"); }
    @Override
    public void unplugin() { System.out.println("UnPlugin-Samsang"); }

    private void enable330V() { System.out.println("330V Start");   }
    private void diable330V(){ System.out.println("330V Stop"); }
}

class SunPower implements Socket {   // [3] //
    @Override
    public void plugin() { System.out.println("Plugin-Sun"); }

    @Override
    public void unplugin() { System.out.println("UnPlugin-Sun"); }

    private void enableSun()  { System.out.println("Sun Start"); }
    private void disableSun() { System.out.println("Sun Stop"); }
}

class Dansang implements Socket {
    @Override
    public void plugin() { System.out.println("Plugin-Dansang"); }

    @Override
    public void unplugin() { System.out.println("UnPlugin-Dansang"); }

    private void enable220()  { System.out.println("Sun 220"); }
    private void disable220() { System.out.println("Sun 220"); }
}
  • Interface [1]에 명시된 메서드는 [2]와 같이 반드시 구현 해야 함
  • Samsng은 Socket이라는 Interface 규격을 따름 -> Realization
  • Interface 실체화 = implements