-
2. OOP(Object Oriented Programming) 상속프로그래밍언어/Java(초급) 2020. 4. 2. 00:32
상속은 재활용 +a 이다
- 객체지향에서의 상속에 대한 논의와 CBD(Component Based Developemnt)
"객체지향 패러다임은 재활용의 관점에서 실패한 패러다임이다."
이는 여러소프트웨어 공학전문가들의 의견이며 내가 읽은 도서와 강의의 의견이다. (맨 아래 참고) 하지만 이 의견은 대부분의 자바기본서에서 말하는 다음의 관점에 위배되는 의견이기도 하다.
"자바에서 상속의 개념은 기존의 클래스를 재활용하여 새로운 클래스를 작성하기 위한 문법으로 정의되어 있다."
상속을 재활용 관점에서 바라보는 것은 문제가 될 수 있다. 상속에 대한 보다 중요한 다른 측면을 보지 못할 수 있기 때문이다. 상속을 통해 연관된 일련의 클래스에 대한 공통적인 규약을 정의할 수 있으며 실제로 이전에 개발해 놓은 클래스의 재활용을 보인 사례는 매우 드물다. 즉 상속은 재활용의 측면에서 바라보면 별로 매력적이지 않다.
그리고 재활용에 대한 이슈는 객체지향 패러다임에서 CBD라는 패러다임으로 옮겨 간지 오래이다.
- 객체지향이 재활용 관점에서 실패한 이유
- 클래스 하나를 재활용하는 것이 새롭게 디자인하는 것보다 더 큰 노력이든다.
- 재활용을 고려해서 클래스를 디자인할 경우, 설계에 필요한 시간이 몇 배 더 길어진다
1. 상속의 정의와 기본적 특징
상속은 클래스간의 상하 관계로 추상적인 슈퍼클래스(Super Class) 혹은 부모 클래스로 부터 서브클래스(Sub Class) 혹은 자식 클래스를 만드는 것으로 상속이라는 관계를 통해 계층구조를 형성한다.
- 슈퍼 클래스에서 정의된 필드와 메서드를 물려 받는다.
- 새로운 필드나 메서드를 추가할 수 있다.
- 슈퍼 클래스에서 물려 받은 메서드를 수정할 수 있다.(오버라이딩, Overriding)
- 동일 슈퍼클래스를 상속하는 모든 서브클래스는 타입 호환이 된다.
이러한 상속을 이용하면 코드의 재사용이 가능해지고 부모클래스 레벨에서 호환되는 서브클래스를 사용해 다형성의 기반을 마련할 수 있다.
프로그램 문법상으로는 extends 키워드를 사용하며 자바의 경우 두개 이상의 클래스를 동시에 상속받는 다중 상속은 지원하지 않지만 추후 포스팅할 인터페이스를 이용해 여러 클래스의 속성을 가지는 서브 클래스 구현이 가능 하다.
상속 예제 Class Man { public Stirng name; //편의상 public public void tellYourName() {System.out.println("My name is " +name); } } Class Bman extends Man{ public String company; publicString position; public void tellYourInfo(){ sout("My comapny is" +company); sout("My position is"+position); tellYourName() //상속으로 호출가능 } }
2. super ()
- super(1, 3, 5) : 상위 클래스의 생성자를 호출하면서 1,3,5를 인자로 전달한다.
public Man(String name) { this.name = name; } public BusinessMan(String name, String company, String position) { super(name); this.company = company; this.position = position; }
new BusinessMan("hyeonWu", "samsung", "programmer");
위 문장선언후 일어나는 일은
- 메모리 공간의 할당
- 모든 인스턴스 변수 초기화
- BusinessMan 생성자 호출 ( 하위클래스 생성자 먼저 호출 된다 )
- Man의 생성자 호출 및 실행 ( 실행은 상위 클래스가 먼저 된다)
- BusinessMan생성자 실행
인스턴스 변수에 별도의 초기화를 진행하지 않으면, 모든 인스턴스 변수는 다음의 디폴트 값으로 초기화 된다.
자료형 디폴트값 int 0 long 0 double 0 boolean false String(or any object) null - 상위 클래스의 생성자는 반드시 호출되어야 한다!
class AAA { int num1; } class BBB extends AAA { int num2; }
위의 경우 다음과 같은 디폴트 생성자가 생성된다
- AAA() {}
- BBB() {super();}
- 다음과 같은 경우는 어떻게 될까?
class AAA { int num1; } class BBB extends AAA{ int num2; BBB() { //super() 자동생성 num2 = 0; } }
하위 클래스 내에 super문이 보이지 않으면, 인자를 전달받지 않는 사우이 클래스의 생성자 호출을 위한 super문이 자동으로 삽입된다. 즉 주석처리한 super() 클래스가 자동으로 생성된다
- 다음과 같이 정의된 클래스의 경우는 어떨까?
class BBB extends AAA { int num2; BBB(){ super(5); //프로그래머에 의해 삽입된 super num2 = 0; } }
이와 같은경우 상위 클래스 AAA에 프로그래머가 입력한 5를 인자로받는 생성자가 존재하지 않으므로 당연히 컴파일 되지 않는다. 임의의 클래스를 정의할 때에는 사우이 클래스에 대한 생성자 정보가 필요하다. 그래야 상위 클래스의 생성자 호출을 위한 super문을 구성할 수 있기 때문이다.
3. protected
- private : 클래스 내부에서만 사용가능
- default : 클래스 내부와 동일한 패키지에서 사용가능
- protected : 클래스 내부와 동일패키지 , 상속받은 클래스 에서 사용가능
- public: 접근 제한 없음
- default와 protected 두 접근제어 지시자를 비교해보자
class AAA { int num1; protected int num2; } class BBB extends AAA { BBB() { num1 = 10; //디폴트 변수에 접근 num2 = 20; // protected 변수에 접근 } }
"num1은 디폴트 멤버이니 접근이 불가능 하지않나?"
라고 생각 할수 있지만 num1도 접근이가능하다 왜냐하면 같은 패키지에 묶이기 때문이다. 즉 protected는 단순히 하위클래스에서의 접근을 허용하는 접근제어 지시자가 아니다. protected는 "다른 패키지에 존재할지라도 상속관계에 놓이면 접근을 허용하는 접근제어지시자" 이다.
- private 멤버도 메소드를 통해 간접 접근이 가능하다
Class Member{ private int val; protected int findid(int num){ val = num; return val; } } class Guest extends Member{ public int findone(int num){ findid(num); } }
Member을 상속받은 Guest는 val 변수에 직접적으로 접근이 불가능하지만 상위클래스가 제공하는 protected 메소드를 통해서 안정적인 형태로 접근이 가능하다. 이렇게 인스턴스 변수를 private로 선언하여 상속시키는 이유는 안정성의 보장에 있다.
Reference
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=4408110
https://dinfree.com/lecture/language/112_java_1.html
'프로그래밍언어 > Java(초급)' 카테고리의 다른 글
3. OOP(Object Oriented Programming) 오버라이딩 (0) 2020.04.07 1. OOP(Object Oriented Programming) 캡슐화 (0) 2020.04.01 5. Collection 프레임워크 (ArrayList vs LinkedList) (0) 2020.03.29 4. StringBuilder & StringBuffer 클래스 다루기 (0) 2020.03.27 3. Java 문자열(String) 다루기 (0) 2020.03.27