프로그래밍/Java

5장정리_OOP

2017. 12. 19. 00:54

Object Oriented Programing. 즉 객체 지향 프로그래밍에 대해서 공부하자.


앞서, 자바는 사람의 사고방식을 반영하여 만들어 졌다는 것을 유의 하자


사람에 사고에는 추상적 상이라는 것이 존재 한다.

예를 들어 우리가 여자를 볼 때 몸의 발달 정도는 어떻고, 머리 길이는 어떻고 

이렇게 디테일한 부분만을 고려하여 여자라는 것을 알기 보다는

우리가 가지고 있는 추상적인 여자라는 상의 빗대어 판단하는 것이다.

이러한 추상적 상 ( Class )이 구체적으로 구현 ( 인스턴스 화 )된 것을 우리는 객체 ( Object )라고 본다. 


Class들은 추상적 원형으로써 구체적인 수치 대신 가장 중요한 특성들만 개략적으로 설정되어 있고,

Object들은 각각 같은 추상적 원형을 가지고 있을 지라도 각각은 독립적인 존재라는 것은

OOP에서 놓치지 말아야 할 특징으로 볼 수 있다.


1. 객체끼리의 상속


대학생, 대학생 알바생, 연구원, 교수

이런 네가지 존재들은 서로 독립된 존재이나 서로 연관없는 존재는 아니다.

모두 사람이라는 속성을 공유하고

대학생과 대학생 알바생은 대학생이라는 속성을

연구원과 교수는 연구원이라는 속성을 공유한다.


이러한 특성은 우리에게 상속의 필요성을 보여준다.

공통적인 속성은 하나의 클래스로 만들고 그 클래스들에 각각의 독립적인 특징들 만을 추가함으로써

클래스의 간결화, 유지 보수의 용이성, 클래스의 재사용 - 확장을 통한

생산성 향상을 가져오는 상속을 굳이 마다할 이유는 없다.


2. JAVA의 상속 선언


키워드

extends

사용 예

class 서브 클래스 extends 슈퍼 클래스


* 상속받는 클래스를 서브 클래스, 상속을 하는 클래스를 슈퍼 클래스라 하며

  부모 클래스, 자식 클래스로도 불린다.


서브 클래스 객체의 모양

상속한 클래스(들)의 멤버 + 자신의 멤버


상속관계에서의 접근 지정자


자바에선 접근 지정자에 따라 슈퍼 클래스 멤버의 접근 가능한 클래스의 종류가 달라진다.


1. 만능 public과 철통 방어 private : 같은 패키지든 다른 패키지든 가리지 않는 성격을 지닌다. 

2. default : 같은 패키지내 클래스와 서브 클래스에 대해서만 접근을 허용한다.

3. protected : default에서 다른 패키지의 클래스 일지라도 그 클래스가 상속관계라면 허용한다.


자바에서 상속의 특징


1. " 클래스"의 다중 상속을 지원하지 않는다.

단, " 인터페이스 "의 다중 상속은 지원한다.

2. 자바의 모든 클래스는 Object 클래스를 자동으로 상속한다.

java.lang.Object 는 유일하게 슈퍼 클래스를 가지지 않는 클래스이다.


생성자의 호출과 실행


앞서, 생성자는 객체내 멤버 초기화에 그 목적을 가진다는 것을 알아두자


서브클래스와 슈퍼클래스의 생성자는 슈퍼클래스의 생성자부터 차례대로 모두 실행된다.

여기서 호출과 실행에 대해 생각해 볼 필요가 있는데 

서브 클래스는 가장 먼저 호출되나 가장 나중에 실행되는 특징을 가진다.

서브 클래스 생성자가 A()이고 슈퍼 클래스 생성자가 B()라면 

A() 호출 -> B() 호출 -> B() 실행 -> A() 실행의 단계가 이루어지는 것이다. 


여러개의 생성자가 있다면 어떻게 실행될 생성자가 결정되는 것일까?

" 명시적 지시가 없을 경우, 슈퍼클래스의 기본 생성자 ( 매개변수가 없는 것 )로 결정한다. "


서브 클래스가 기본 생성자였건 매개변수를 가진 생성자였건 무조건 저 규칙을 따르게 된다.

그리하여 만약 명시가 되있지 않은 상태에서 슈퍼클래스가 기본 생성자를 가지고 있지 않다면 

자바 컴파일러는 오류를 출력한다.

자바 컴파일러가 기본 생성자를 강제로 삽입하기도 하지만

이는 클래스 내의 아무런 생성자도 선언되있지 않은 경우일때만 해당하기 때문이다.


super( )

그렇다면 명시적 선언은 어떻게 해주는 것일까?

그럴때 사용되는 것이 super( )이다.

이 것은 슈퍼 클래스 생성자의 호출을 의미하며 괄호안에 매개변수를 주어 

기본 생성자가 아닐지여도 호출이 가능하다.


주의 사항이 한가지 있다.

super( )의 호출이 반드시 생성자의 첫 라인에 와야 한다는 것이다.

그럴만도 한게 바로 슈퍼클래스 호출로 넘어가면 명시적 선언에 의미가 사라져 버리기 때문에

super( )를 체크하고 넘어가도록 해주는 것이다.


3. 업캐스팅과 instanceof 연산자


캐스팅은 타입 변환을 말하는데 자바에서 클래스에 대한 캐스팅은 업캐스팅과 다운캐스팅으로 나뉜다.


업캐스팅

서브 클래스 객체가 슈퍼 클래스 타입으로 변환되는 것.


왜 할까?

여러가지 견해가 있지만 주관적인 생각으로는 객체의 관리 및 활용의 용이성을 들 수 있다.

업캐스팅이 있음으로써 자바는 공통된 속성단위로 객체들을 처리 가능하기 때문이다.


접근성

객체내의 슈퍼클래스 ( 현재 바뀐 타입 )의 멤버만 접근 가능하다.

해당 슈퍼클래스로 처리되는 것이기 때문이다.

또한 명시적 타입 변환을 안해주어도 무방하다.

p = (Person)s; 이런식으로 안해주어도 p = s; 만으로 가능하다.

그 이유는 s가 이미 p타입이기 때문이다.


다운캐스팅

업캐스팅된 서브클래스를 다시 원래대로 되돌리는 것

당연히 " 변환할 타입 명시 "가 요구된다.


그렇다면 업캐스팅 상태의 레퍼런스들이 가르키는 객체를 어떻게 구별할까 

그 해답이 바로 instanceof 연산자이다.


instanceof

사용 예 : 객체 레퍼런스 instanceof 클래스 타입

이항 연산자로서 레퍼런스가 가리키는 객체가 해당 타입일시 true를 반환한다.

이를 통하여 구별이 가능한 것이다.


클래스에만 적용된다는 것에 주의 하자 ( 3 instanceof int )


4. 메소드 오버라이딩


메소드 오버라이딩

서브 클래스에서 슈퍼 클래스에 선언된 메소드를 중복 작성하여 

슈퍼 클래스의 메소드를 무력화 시켜

슈퍼클래스의 레퍼런스를 이용하든 서브 클래스의 레퍼런스를 이용하든

항상 서브 클래스의 오버라이딩한 메소드가 실행되도록 하는 것


* 나도 헷갈렸던 것은 슈퍼클래스에서 해당 메소드를 호출시 

서브 클래스에서 호출 된다는 사실이다 ㄷㄷ.. 

이러한 현상은 동적 바인딩에 의해 가능하다.


왜 할까?

다형성의 실현이 주 목적이다.

자신이 원하는 부분에 대해선 새롭게 정의 함으로써

하나의 인터페이스에 서로 다른 내용을 구현하는 것이다.


* 다형성

가장 이해하기 쉬운 예로는 종의 다형성이 있다.

같은 종의 생물이지만 모습이나 특징이 다양한 특징을 의미한다.


자바는 인간세계를 구현해놓은 것으로 보면 편하므로

다형성의 필요성까지도 생각해볼 수 있을 것이다.


동적 바인딩

실행할 메소드를 컴파일 시에 결정하지 않고 실행 시에 결정하는 것


super 키워드

오버라이딩에 의해 슈퍼 클래스의 메소드는 더 이상 실직한 것일까?

결론부터 말해주면 No 이다.


우리는 super 키워드를 이용하여 정적바인딩을 통해 슈퍼 클래스의 멤버에 접근 가능하다.

그렇담 super은 무엇인가.


super은 슈퍼 클래스에 대한 레퍼런스이다.

( 정확히 바로 한단계위 슈퍼 클래스를 가리키고 있다. _ 테스트 결과 )


정적 바인딩

실행할 메소드를 컴파일 시에 결정하는 것


메소드의 오버로딩 ( overloading )과 오버라이딩 ( overriding )

비슷해보이는 오버 로딩과 오버라이딩에 대해 비교 분석을 해보자


우선 존재 목적을 비교해보자


오버 로딩은 이름을 공유하고 타입, 메소드의 인자 개수를 다르게 하여 

메소드 사용의 편리성을 향상시키는게 목적이고, 


오버 라이딩은 완전히 똑같은 형태에 내용물을 바꾸어 바꾼 내용물이 

기존의 것을 대체하도록 하는 것이 목적이다.


조건을 비교해보면 목적에 맞게 오버 로딩은 이름을 제외하고 하나라도 달라야 되고

오버 라이딩은 모두 같아야 한다.


이렇기 때문에 오버로딩은 정적 바인딩, 오버라이딩은 동적 바인딩을 사용하는 것이다.


* 내가 모르고 있었던 부분은 메소드 오버로딩이 같은 클래스내에서 뿐 아니라

상속 관계에서도 이루어 질 수 있었다는 사실이였다. *


5. 추상 클래스


추상 메소드

abstract 키워드와 함께 원형만 선언되고, 코드는 작성되지 않은 메소드


추상 클래스

abstract로 선언한 클래스, 추상 메소드가 있을 수도 없을 수도 있다.


추상 메소드를 가지고 있을 경우 반드시 추상 클래스이다.

추상 클래스는 레퍼런스 선언은 가능하나 말 그대로 추상적인 존재기 때문에

인스턴스( 객체 ) 생성이 불가능하다.


추상 메소드를 가진 추상 클래스를 상속받는 서브 클래스는

자동으로 추상 클래스가 된다.

이는 추상 메소드를 상속받기 때문이다.

이때 서브클래스에 abstract를 붙여 추상클래스임을 명시하는 것이 요구된다.


추상 클래스의 구현

슈퍼 클래스의 모든 추상 메소드를 오버라이딩하여 실행 가능한 코드로 구현하는 것

당연히 정상 클래스이므로, 인스턴스화도 가능하다.


왜 있는 것일까?

메소드의 오버라이딩의 존재 이유였던 다형성이 여기서도 명시된다.


* 주의 할점은 구현되지 않은 추상 메소드가 하나라도 남아 있다면 그 클래스는 추상 클래스이다.

* 내가 헷갈렸던 것 *

abstract class A {

void f() {}

}

class B extends A {

}

위 코드에서 f()는 원형이 아니므로 즉 추상 메소드가 아니므로 A는 추상 클래스가 아니여도 된다.

그런데 추상 클래스라고 선언을 하였기 때문에 A의 인스턴스화는 이 상황에서도 불가능하다.

하지만 B는 추상 클래스를 상속받았더라도 추상 메소드를 상속 받지 않았으므로 

추상 클래스가 아니며 그렇기에 인스턴스화가 가능하다.


6. 인터페이스 ( interface )


인터페이스

규격.

자바 인터페이스

키워드 :  interface

구성 : 상수 필드 + 추상 메소드들

특징

상수 필드는 기본이 public static final 속성이다.

추상 메소드는 abstract를 생략하고 적어도 된다.

인터페이스끼리의 상속이 가능하다.


interface A {

double pi = 3.141592;

void f1();

void f2();

}


 당연히 인스턴스화가 불가능하다.

추상적 상 그 자체이기 때문


인터페이스는 다중 상속과 다중 구현이 가능하다. 각각의 인터페이스는 ,로 구별한다.


인터페이스의 구현

 키워드 : implements

 특징

모든 추상 메소드를 구현해야만 한다.

추가적으로 다른 메소드를 작성하여도 무방하다.




( 기타 ) 

인상적이였던 문제


슈퍼클래스 A, 서브클래스 B일때

b = (B) new A(); 가 컴파일 오류는 없지만 실행 오류가 나는 이유는 ?


[ A ] 

새로운 A객체를 B 타입으로 캐스팅하게 되면 아직 객체화 되지 않는 B의 멤버를 접근 가능하게 해주는 꼴이 되기 때문에 오류가 발생한다.


추상 클래스 선언이 잘못된 것은?

[ A ] 

abstract class A {

void f();

}


진짜 진짜 틀릴뻔 했다.

함수의 원형만 적을땐 꼭꼭 abstract를 적어주자!!!













'프로그래밍 > Java' 카테고리의 다른 글

8장정리_자바GUI_Swing  (0) 2017.12.19
6장정리_자바패키지활용  (0) 2017.12.19
7장정리_컬렉션과제네릭  (0) 2017.12.19
12장정리_자바스레드  (0) 2017.12.19
Prolog_171218  (0) 2017.12.18