개발/Java

☕Java:: {Inheritance(상속)} rough note

hyuunii 2022. 9. 4. 19:25

상속 - 1 개괄

아래 보면 위에꺼가 밑에꺼의 부모. 위에꺼를 그대~로 상속받고 거기다가 원하는걸 추가하는거임.

java.lang.Object

java.io.Writer

java.io.PrintWriter

자바의 가장 기본적인 클래스는 오브젝트클래스. 모든 클래스는 오브젝~을 반드시 상속받음. 상속받을 때 쓰는 키워드가 extends(PrintWriter extends Writer 이렇게 씀)


상속 - 2 Overriding & Overloading

* Overriding: (부모 클래스를 자식 클래스의) 등에 업는다는 사전적 의미. 상속의 개념으로 부모 클래스에 있는 메소드나 변수를 extends를 통해 굳이 같은 형태의 메소드를 입력하지 않아도 부모클래스에 있는 메소드를 끌어다 쓸 수 있는 기능이다.

응용으로 수정, 추가 또한 가능하다. ex) System.out.println("Cal3!!");

☞오버라이딩: 유지보수가 편리하고, 코드의 양을 줄이며 가독성을 높인다.

* Overloading: 기능을 과적시킨다는 사전적 의미. Overriding과 이름이 비슷하지만 조금 다른 개념. '상속'이라는 것과는 조금 멀리 떨어져 봐야할 필요가 있다. Overriding이 부모 클래스의 멤버들을 이용할 수 있다면, Overloading은 부모 클래스가 갖고 있는 메소드의 형태를 자식 클래스에서 조금 바꿔 "이름을 같게" 사용할 수 있다(메소드의 매개변수 타입, 개수변화 등등.)

원래 메소드란 이름이 같을 수 없는데 이 경우 가능하다.

☞오버로딩 : 상속과 관계가 없다. 정의 되는 위치가 부모 또는 자식 어느 쪽에서 구현을 하던 상관이 없다는 의미.


상속 - 3 this와 super

* this: 자식 클래스 내에 있는 메소드를 지칭

* super: 부모 클래스 내에 있는 메소드를 지칭

<super>

public int sum(int v1, int v2){

System.out.println("Cal3!!");

return v1+v2;

}

위는 아래의 부모 클래스의 sum을 override함.

public int sum(int v1, int v2){

return v1+v2;

}

이 때, 부모 클래스의 코드 v1+v2가 짧기에 망정이지 1억줄짜리 jonna 복잡하다면? 자식 sum에서 그대로 갖다 쓰는게 힘들고 오류 가능성 높.

그러니 '계승과 발전'을 하자. 어떻게? 자식 sum 이 부모 sum을 그대로 호출하고, 그 결과를 이용하게!! 이때 이용하는게 super

public int sum(int v1, int v2){

System.out.println("Cal3!!");

return super.sum(v1,v2);

}

<this>

class Cal{

public int sum(int v1, int v2){

return v1+v2;

}

// Overloading

public int sum(int v1, int v2, int v3){

return this.sum(v1,v2)+v3;

}

}

아래의 sum은 바로 위 sum이라는 메소드의 기능을 그대로 내부적으로 가진 채 계승, 발전 시킨다. 이 때, 아래의 sum에서

public int sum(int v1, int v2, int v3){

return sum(v1,v2)+v3;

}

얘도 그대로 작동하지만

public int sum(int v1, int v2, int v3){

return this.sum(v1,v2)+v3;

}

이렇게 명시적으로 this를 붙여주면 이 this가 자기 자신을 가리키기에, 자기 자신(v1+v2라는 원래의 메소드)에다가 v3를 더해서 연산 결과를 만들어 냄.


상속 - 4 상속과 생성자

생성자가 있는 부모 클래스를 상속받으려면 생성자도 함께 상속 받아야 한다.

Cal3(int v1, int v2) {

super(v1, v2);

해당 부분이 그부분, 하지만 이때는 this가 아닌, super를 써서 부모 클래스의 생성자임을 명확하게 하고, 부모에게서 상속받은 생성자임을 확실히 한다.

생성자는 이전에도 배운 개념이지만, 초기화 하는 준비과정에서 일련의 과정들을 강제화시켜 사람들이 프로그래밍을 조금더 개발자의 의도에 맞게 쉽게 따라갈 수 있도록 하는것이다. (특정값을 집어넣어야만 작동되게 한다던지)

상속에서도 생성자까지 상속하게 된다면 확장된 클래스에서도 초기에 세팅된 값을 쓰게 되므로 불필요한 사용자의 탐구가 줄어들게 되며, 상속된 클래스까지 그 값을 사용하게 되므로 효율성과 재확장성이 늘어남을 알 수 있다.

super라는 것으로 부모의 생성자 인자를 받아왔기 때문에, 해당 상속 클래스에서 그 값이 그대로 쓰일 수 있는데,

상속 클래스에서 새롭게 메소드를 작성했을때에 리턴값에 this 가 어디에 속해져있는지 조금 헷갈릴 수 있다.

이 this는 부모에게서 상속받은 생성자의 인자값인데, 이것이 이미 상속되어 Cal3 이라는 클래스 내부의 값이 되었기 떄문에 Cal3에서의 this의 값으로 정의되어 표현된다. v1,v2의 값을 재정의할수도 있겠지만.. 생성자로서 상속받은 값을 굳이 재정의할 이유와 논리적인 이유가 없기에 그냥 쓰자. 생성자를 쓰는 이유가 그런것 아닌가? 굳이 재정의할 이유가..


상속 - 5 마치며

상속을 하면 기능이 급격하게 늘어남

클래스들 간의 호환성이 떨어지게 되고 클래스를 다른 클래스로 교체하는 것이 어려워짐

이런 맥락에서 자식 클래스, 부모 클래스로서 동작하도록 규제하는 것이 다형성(Polymorphism)

✔접근 제어자(Access Modifiers)

- `public`, default, `protected`, `private` 등과 같은 키워드

- 클래스, 메소드, 변수를 사용자들이 아무거나 건드리지 못하게 제한하는 기능(비전문가가 전자제품 내부를 맘대로 건들면 고장남. 클래스도 마찬가지. 사용자에게 제공하려고 하는 조작 장치만 손댈 수 있도록 하고, 그 외에는 건드리지 못하도록 규제하는 것)

Final 기능

- 내가 만든 클래스를 다른 사람들이 더이상 상속하지 못하게 하거나

- 메소드를 오버라이딩 하지 못하게 하거나

- 변수를 마음대로 수정하지 못하게 하는 규제.

Abstract 기능

- 클래스를 상속해서 사용하려는 사용자에게 어떤 특정한 메소드는 꼭 구현하라고 강제.

- 상속자가 직접 구현해야 하는 기능을 구현하도록 강제.