Home [Java] OOP 심화
Post
Cancel

[Java] OOP 심화

객체지향 프로그래밍의 4개의 기둥

상속 (Inheritance)

상속 (Inheritance)

  • 상위클래스의 멤버(필드, 메서드, 이너클래스)를 하위클래스에게 확장시키는 것
  • 하위클래스의 멤버는 상위클래스의 멤버와 같거나 많다
  • 코드의 재사용성
  • 코드의 중복 제거
  • 다형적 표현 가능
  • 자바는 단일 상속만 가능(다중상속X)
    • 인터페이스(interface)를 통해 다중상속과 비슷한 효과를 낼 수 있다
  • Object 클래스는 자바의 클래스 상속계층도의 최상위 위치
  • 모든 클래스는 Object 클래스에게서 상속받는다

Object 클래스 대표 메서드

메서드명반환타입내용
toString()String객체정보를 문자열로 출력
equals(Object o)boolean등가 비교 연산과 동일하게 스택 메모리값 비교
hashCode()int객체 위치정보관련. Hashtable 또는 HashMap에서 동일 객체여부 판단
wait()void현재 쓰레드 일시정지
notify()void일시정지 쓰레드 재동작

포함관계 (composite)

  • 상속처럼 클래스를 재사용하는 방법
  • 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것
관계판별기준(클래스간의 관계상태)적합관계
~는 ~이다 (IS-A)상속관계
~는 ~를 가지고있다 (HAS-A)포함관계

메서드 오버라이딩 (Method Overriding)

  • 상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것
  • 메서드 오버라이딩 사용 시 조건
    1. 메서드의 선언부(메서드 이름, 파라미터, 반환타입)이 상위클래스와 완전히 일치
    2. 접근 제어자의 범위가 상위 클래스의 메서드보다 같거나 넓어야함
    3. 예외는 상위 클래스의 메서드보다 많이 선언 불가
    4. 인스턴스 메서드를 static 또는 그 반대로 변경 불가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class InheritanceExample {
  public static void main(String[] args) {
    Apple apple = new Apple(); // 각각의 타입으로 선언 + 객체 생성
    Banana banana = new Banana();
    Orange orange = new Orange();

    // 오버라이딩되어 각각 다른 출력
    apple.taste();
    banana.taste();
    orange.taste();

    > 출력
    > Apple is sweet!
    > Banana is sweet!
    > Orange is sweet!
------------------------------------------------------- 
    Fruit apple2 = new Apple(); // 상위 클래스 타입으로 선언 + 각각 타입으로 객체 생성
    Fruit banana2 = new Banana();
    Fruit orange2 = new Orange();

    apple2.taste();
    banana2.taste();
    orange2.taste();

    > 출력
    > Apple is sweet!
    > Banana is sweet!
    > Orange is sweet!
------------------------------------------------------
    // 배열로 한번에 관리하기
    Fruit[] fruits = new Fruits[] {new Apple(), new Banana(), new Orange()};
    for (Fruit fruit : fruits) {
      fruit.taste();
    }

    > 출력
    > Apple is sweet!
    > Banana is sweet!
    > Orange is sweet!
  }
}

class Fruit {
  void taste() {
    System.out.println("Fruit is sweet!");
  }
}

class Apple extends Fruit {
  void taste() {
    System.out.println("Apple is sweet!");
  }
}

class Banana extends Fruit {
  void taste() {
    System.out.println("Banana is sweet!");
  }
}

class Orange extends Fruit {
  void taste() {
    System.out.println("Orange is sweet!");
  }
}

super 키워드 : 상위 클래스의 객체 호출

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Super {
    public static void main(String[] args) {
        Lower low = new Lower();
        low.callNum();
    }
}
 
class Upper {
    int count = 20; // super.count
}
    
class Lower extends Upper {
    int count = 10; // this.count
      
    void callNum() {
        System.out.println("count = " + count);
        System.out.println("this.count = " + this.count);
        System.out.println("super.count = " + super.count);
    }
}
    
> 출력
> count = 15
> count = 15
> count = 20

super() 메서드 : 상위 클래스의 생성자 호출

  • 생성자 안에서만 사용 가능
  • 생성자 첫 줄에 와야함
  • 첫 줄에 없는 경우 컴파일러가 자동으로 삽입함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SuperMethod {
  public static void main(String[] args) {
    CoffeeMilk m = new CoffeeMilk();
  }
}

class Coffee {
  Coffee() {
    System.out.println("커피 생성자");
  }
}

class CoffeeMilk extends Coffee { // Coffee 로부터 확장(상속)
  CoffeeMilk() {
    super(); // Coffee 클래스의 생성자 호출
    System.out.println("커피우유 생성자");
  }
}

> 출력
> 커피 생성자
> 커피우유 생성자

캡슐화 (Encapsulation)

캡슐화 (Encapsulation)

  • 특정 객체 안에 관련된 속성과 기능을 하나의 캡슐로 만들어 데이터를 외부로부터 보호하는 것
  • 캡슐화 목적
    • 데이터 보호
    • 내부적으로만 사용되는 데이터에 대한 불필요한 외부 노출 방지

캡슐화 장점

  • 정보은닉 (data hiding).
  • 외부로부터 객체의 속성과 기능이 변경되지 못하도록 막고, 데이터가 변경되더라도 다른 객체에 영향을 주지 않기 때문에 독립성 확보
  • 유지보수, 코드 확장 시 오류범위 최소화

패키지 (package)

  • 특정한 목적을 공유하는 클래스와 인터페이스 묶음
  • 클래스들을 그룹단위로 묶어 효과적 관리 위한 목적
  • 자바에서의 패키지는 하나의 디렉토리이고 .으로 구분됨
  • package java.util.*;

Import문

  • 다른 패키지 내의 클래스를 사용하기 위해 사용
  • 패키지문과 클래스문 사이에 작성
1
2
3
4
5
6
7
package practicePackage.test; // package문

import practicePackage.test2; // import문 작성

public class PackageImp {
  ...생략...
}

접근제어자 (Access Modifier)

  • 제어자 (Modifier) : 클래스, 필드, 메서드, 생성자 등에 부가적인 의미 부여 키워드. 자바에서는 접근제어자와 기타제어자로 구분.
접근제어자public, protected, default(미작성 시 기본설정), private
기타제어자static, final, abstract, native, transient, synchronized 등
  • 접근제어자 (Access Modifier)
    • 외부로의 불필요한 노출 방지
    • 데이터 임의 변경 방지
    • 필드나 메서드 선언부 앞에 적어서 접근 범위 제한
접근제어자클래스 내패키지 내다른 패키지의 하위 클래스패키지 외
PrivateOXXX
DefaultOOXX
ProtectedOOOX
PublicOOOO

getter / setter 메서드

  • 데이터 보호 위해 private로 선언 시, 객체의 변수의 데이터값을 추가 및 수정 불가
  • 그 때, getter 메서드로 데이터 값을 가져올 수 있음
  • 그 때, setter 메서드로 데이터 값을 수정할 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class updateNum {
  public static void main(String[] args) {
    GetSetNum getSetNum = new GetSetNum(25);
    System.out.println(getSetNum.getNum());

    getSetNum.setNum(50);
    System.out.println(getSetNum.getNum());
  }
}

class GetSetNum {
  private int num;

  GetSetNum(int num) {
    this.num = num;
  }

  // getter 사용시 메서드명은 get-
  public int getNum() {
    return this.num;
  }

  // setter 사용시 메서드명은 set-
  public void setNum(int num) {
    this.num = num;
  }
}

> 출력
> 25
> 50

다형성 (Polymotohism)

다형성 (Polymorophism)

  • 한 타입의 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것
    • 상위 클래스 타입의 참조변수를 통해 하위 클래스의 객체를 참조할 수 있도록 허용한 것
    • 위 방법으로 선언한 객체는 상위클래스의 멤버만 사용 가능
  • 장점 : 코드의 중복을 줄여준다
  • 메서드 오버라이딩과 메서드 오버로딩도 다형성의 한 예시

참조변수의 타입 변환 : 사용할 수 있는 멤버의 개수를 조절하는 것

  • 타입 변환 조건 3가지
    1. 서로 상속관계에 있는 상위 - 하위 클래스 사이만 타입변환 가능
    2. 하위클래스 -> 상위클래스로의 타입변환(업캐스팅)은 형변환 연산자(괄호) 생략 가능
    3. 상위클래스 -> 하위클래스로의 타입변환(다운캐스팅)은 형변환 연산자를 반드시 명시해야함
1
2
3
4
5
6
7
8
9
10
11
public class CastingExample{
  public static void main(String[] args) {
    ParentClass parentClass = new ParentClass();
    ChildClass childClass = new ChildClass();

    ParentClass upcasting1 = childClass;
    ParentClass upcasting2 = (ParentClass) childClass;

    //ChildClass downcasting1 = parentClass; // 형변환연산자 생략 불가 Incompatable Type
    ChildClass downcasting2 = (ChildClass) parentClass; // ClassCastException 발생
}

instanceof 연산자

  • 캐스팅 가능 여부를 boolean 형으로 반환하는 자바문법요소
  • 프로젝트 규모↑, 클래스↑ 사용시 좋음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class InstanceOfExample {
  public static void main(String[] args) {
    Animal animal = new Animal();
    System.out.println(animal instanceof Object); //true
    System.out.println(animal instanceof Animal); //true
    System.out.println(animal instanceof Bat); //false

    Animal cat = new Cat();
    System.out.println(cat instanceof Object); //true
    System.out.println(cat instanceof Animal); //true
    System.out.println(cat instanceof Cat); //true
    System.out.println(cat instanceof Bat); //false
  }
}

class Animal{};
class Bat extands Animal{};
class Cat extends Animal{};

추상화 (Abstraction)

추상화(Abstraction)

  • 기존의 클래스들의 공통적인 요소들을 뽑아서 상위 클래스를 만들어 내는 것
  • 주로 추상 클래스인터페이스라는 문법 요소로 구현

추상화 장점

  • 코드의 중복 제거
  • 효과적인 클래스간의 관계설정
  • 유지보수 용이

abstract 제어자

  • 주로 클래스와 메서드를 형용하는 키워드로 사용

  • 메서드 앞에 붙은 경우 ‘추상 메서드(abstract method)’

    • 메서드의 시그니처만 있고 바디는 없는 메서드
    • abstract 키워드를 메서드 이름 앞에 붙여주어 해당 메서드가 추상메서드임을 표시
    • 추상메서드는 미완성 메서드
    • 미완성 메서드를 포함하는 클래스는 미완성 클래스를 의미하는 추상 클래스
  • 클래스 앞에 붙은 경우 ‘추상 클래스(abstract class)’

    • 추상메서드를 하나 이상 갖고있는 클래스
    • abstract 키워드를 클래스 이름 앞에 붙여주어 해당 클래스가 추상클래스임을 표시
    • 추상클래스로 객체선언 불가

추상클래스 사용 이유

  • 상속 관계에 있어 새로운 클래스를 작성하는데 매우 유용

    • 메서드 내용이 상속받는 클래스에 따라 달라지는 경우 상위클래스의 선언부만 작성한 뒤 구체적 내용은 하위클래스에서 구현하도록 비워두는 것
  • 추상화를 구현하는 핵심 역할

    • 상속계층도의 상층부에 가까울수록 공통적인 속성과 기능들이 정의

final 키워드

위치의미
클래스변경 또는 확장 불가능한 클래스, 상속 불가
메서드오버라이딩 불가
변수값 변경이 불가한 상수

Interface

  • 모든 필드는 public static final로 선언
  • 모든 메서드는 static, default 이외에는 public abstract로 정의

Interface 구현

  • 인터페이스 그 자체로 객체생성 불가
  • 메서드 바디를 정의하는 클래스를 따로 작성해야함
  • implements 키워드 사용
  • 특정 인터페이스를 구현한 클래스는 해당 인터페이스에 정의된 모든 추상메서드를 구현해야함
  • 다중 구현 가능

Interface 구현 장점

  • 역할과 구현의 분리
    • 복잡한 구현 내용 또는 변경과 상관없이 기능 사용 가능
  • 개발시간 단축
  • 독립적인 프로그래밍을 통해 한 클래스의 변경이 다른 클래스에 미치는 영햔 최소화
This post is licensed under CC BY 4.0 by the author.