일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- MySQL
- 자연어 논문 리뷰
- 코딩테스트
- sigmoid
- LSTM
- Statistics
- 서브쿼리
- 설명의무
- CASE
- 자연어 논문
- NLP
- HackerRank
- 논문리뷰
- inner join
- torch
- sql
- 그룹바이
- SQL 날짜 데이터
- 표준편차
- leetcode
- nlp논문
- t분포
- 자연어처리
- GRU
- update
- 짝수
- 카이제곱분포
- Window Function
- airflow
- SQL코테
- Today
- Total
HAZEL
[ CH03. 객체지향 핵심 ] 상속 , 형변환, super 키워드 , overriding , 다형성, 다운 캐스팅, instanceof 본문
[ CH03. 객체지향 핵심 ] 상속 , 형변환, super 키워드 , overriding , 다형성, 다운 캐스팅, instanceof
Rmsid01 2021. 4. 5. 15:37CH03. 객체지향 핵심
: 패스트 캠퍼스 강의를 공부하고 정리한 내용입니다.
01. 상속
1. 클래스 상속
: 클래스를 정의할 때, 이미 구현된 클래스를 상속 받아서 속성이나 기능을 확장하여 클래스를 구현함
: 이미 구현된 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할 때, 기존 클래스를 상속함
- 상위 클래스 = parent class = base class = super class
- 하위 클래스 = child class = derived class = subclass
2. 상속하기
class B extends A {
}
: B(하위) A(상위)
: A의 클래스를 확장한다는 개념인데, A는 한개의 클래스만 올 수 있다. - 자바는 단일 상속 만 지원함
( 인터페이스에서는 여러개의 상속도 가능하다 )
3. 상속을 구현하는 경우
: 상위 클래스와 하위클래스 보다 더 일반적.
: 하위 클래스가 상위 클래스의 속성과 기능을 확장한다는 의미!
4. protexted 접근 제어자
: private 멤버 변수는 하위 클래스에 접근 못한다! 그래서, 외부 클래스는 접근할 수 없지만, 하위 클래스는 접근할 수 있도록 protected를 사용한다.
- 멤버변수를 만들려면 메모리가 있어야한다! 그런데, 아래에는 없다! 왜냐하면 상위 클래스에 이미 있기 때문이다!
public class VIPCustomer extends Customer {
private int agentID; // 담당하는 상담원 아이디
double salesRatio;
// customer 구현되 내용이 중복이므로 customer를 확장하여 구현함 ( 상속 ) - 상속받았기 때문에, 이미 있는 변수는 초기화 안해두됨
// 생성자
public VIPCustomer(){
customerGrade = "VIP"; // 상속을 받으려니깐, 오류발생 - 왜냐면 , privite 이기 때문 - 클래스 내부에만 사용
// 하지만 상속관계에서는 사용할일이 많음. - 외부는 못해도 하위는 접근 가능하게 해랏 -> protected로 변경
bounsRatio = 0.05;
salesRatio = 0.1;
}
}
5. 하위 클래스가 생성되는 과정
customer() call
Vipcustomer() call
customer(int, string) call
이순신님의 등급은 BASIC이며, 보너스 포인트는 1000입니다.
customer(int, string) call
Vipcustomer(int, string) call
Kim님의 등급은 VIP이며, 보너스 포인트는 1000입니다.
: 하위 클래스를 호출하면 -> 상위 클래스가 호출되고, 하위 클래스가 호출된다.
아무코드도 없는데 어떻게 상위 클래스가 호출이 되는가?
- 클래스 생성자가 상속을 받은 경우에는, 컴파일러가 super(); 를 넣어주게 됨.
6. super() 키워드
: 생성된 상위 클래스 인스턴스의 참조값을 가지므로 super를 이용하여 상위 클래스의 메서드나 멤버 변수에 접근할 수 있다.
: 상위 클래스의 기본 생성자를 호출함. - 하위 클래스에서 명시적으로 상위 클래스의 생성자를 호출하지 않으면, super()가 호출됨.
: 내가 직접 코드로 입력하지 않아도, 컨파일러가 알아서 적고 프로그래밍 해준다. ( 묵시적으로 ) - 직접써주는 일은 거의 없음.
: 만약, 상위 클래스의 기본 생성자가 없는 경우, 내가 직접 하위 클래스에서 super을 이용하여, 명시적으로 상위 클래스의 생성자를 호출해야한다.
// 생성자로 호출 받는 법
public VIPCustomer(){
super(0,"no-name");
customerGrade = "VIP";
bounsRatio = 0.05;
salesRatio = 0.1;
System.out.println("Vipcustomer() call"); // 얘가 불렸을때 출력되는 로그
}
// 생성자를 안쓰고 이렇게 써도 가능 - 위에랑 같은 코드
public VIPCustomer(int customerID, String cutomerName){
super(customerID, cutomerName);
customerGrade = "VIP";
bounsRatio = 0.05;
salesRatio = 0.1;
}
// test코드
public static void main(String[] args) {
Customer customerLee = new Customer(10010, "이순신"); // test코드
7. 상속에서 인스턴스 메모리의 상태
: 항상 상위 클래스의 인스턴스가 생성된 후에 하위 클래스의 인스턴스가 생성된다.
8. 형 변환(업캐스팅)
: 상위 클래스로 변수를 선언하고 하위 클래스의 생성자로 인스턴스를 생성 , 단 이 역은 성립 하지 않음
: 즉, 아래처럼 코드를 작성할 수 있다.
Customer customerLee = new VIPCustomer();
- 이렇게 할수있는 이유는, vip를 생성하면, customer을 내포하고 있기 때문에, 이 타입으로 형변환 되는 것은 가능하다.
즉, vipcustomer 의 인스턴스는 customer 타입으로 대입될 수 있음.
VIPCustomer vCustomer = new VIPCustomer();
addCustomer(vCustomer);
int addCustomer(Customer customer){
}
- 즉, 상위 클래스로 형변환이 됨. <-> 원래 자기 인스턴스로 되는것 - 다운 캐스팅
: 아래 사진과 같이, customer로 형변환이 되면, 인스턴스는 vip를 받지만, 고유한 vip의 변수나 메서드는 사용하지 못한다.
즉, customer 것만 사용가능하다.
02. 메서드 재정의하기 ( overriding )
1. 하위 클래스에서 메서드 재정의하기
- 오버라이딩 : 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있다.
# 주의점 : 반환값, 메소드이름, 매개변수의 타입과 갯수가 동일해야함. . 맞지 않을 경우 다른 메소드로 처리됨.
@Override // 컴파일에게 정보를 제공해주는 역할
public int calcPrice(int price) {
bounsPoint += price * bounsRatio;
price -= (int)(price * salesRatio);
return price;
}
2. 애노테이션 ( annotation )
: 컴파일러에게 특별한 정보를 제공해주는 역할
- 애노테이션의 종류
1) @Overrride : 재정의된 메서드라는 정보 제공
2) @Fuctionallnterface : 함수형 인터페이스라는 정보 제공
3) Deprecated : 이후 버전에서 사용되지 않을 수 있는 변수, 메서드에 사용
4) @SuppressWarnings : 특정 경고가 나타나지 않도록 함
3. 형 변환과 오버라이딩 메서드 호출
: vs 변수의 타입은 Customer지만 인스턴스의 타입은 VIPCustomer 이다. 자바에서는 항상 인스턴스의 메서드가 호출됨. (가상 메서드의 원리), 자바의 모든 메서드는 가상 메서드 ( virtual method ) 이다.
Customer vc = new VIPCustomer(1234, "noname"); // 형변환 가능
System.out.println( vc.calcPrice(1000)); // 900
03. 메서드 재정의와 가상 메서드 원리
1. 메서드 호출 및 실행 방법
- 자바는 그냥 가상함수 메서드
- 메서드(함수)의 이름은 주소값을 나타냄
- 메서드 명령어의 set이고 프로그램이 로드되면 메서드 영역(코드 영역)에 명령어 set이 위치
- 해당 메서드가 호출 되면 명령어 set 이 있는 주소를 찾아 명령어가 실행됨
- 이때 메서드에서 사용하는 변수들은 스택 메모리에 위치 하게됨
- 따라서 다른 인스턴스라도 같은 메서드의 코드는 같으므로 같은 메서드가 호출됨
- 인스턴스가 생성되면 변수는 힙 메모리에 따로 생성되지만, 메서드 명령어 set은 처음 한번만 로드 됨
public class TestMethod {
int num;
void aaa(){
System.out.println("TestMethod.aaa 호출");
}
public static void main(String[] args) {
TestMethod a1 = new TestMethod();
a1.aaa();
TestMethod a2 = new TestMethod();
a2.aaa();
}
}
04. 다형성 ( polymorphism )
1. 다형성 이란 ?
- 하나의 코드가 여러 자료형으로 구현되어 실행되는 것. 같은 코드에서 여러 다른 실행 결과가 나옴
- 객체지향 프로그래밍의 가장 큰 특징 중 하나임 -> 유연하고 확장성있고, 유지보수가 편리한 프로그램을 만들수 있음
2. 다형성을 사용하는 이유?
- 다른 동물을 추가하는 경우
- 상속과 메서드 재정의를 활용하여 확장성 있는 프로그램을 만들 수 있음
만약, 안그렇게 한다면, if-else 문이 너무 많이 구현되서 코드의 유지보수가 어려워짐
- 상위 클래스에서 공통적인 부분을 제공하고 하위 클래스에서는 각 클래스에 맞는 기능 구현
- 여러 클래스를 하나의 타입(상위 클래스)으로 핸들링 할 수 있음
05. 상속을 사용하는 경우
1. IS-A관계 ( is a relationship : ingeritance )
- 일반적인(general) 개념과 구체적인(specific) 개념과의 관계
- 상위 클래스 : 하위 클래스보다 일반적인 개념 ( 예: Employee )
- 하위 클래스 : 상위 클래스보다 구체적인 개념들이 더해짐 ( 예: Engineer, Manager...)
- 상속은 클래스간의 결합도가 높은 설계
- 상위 클래스의 수정이 많은 하위 클래스에 영향을 미칠 수 있음
- 계층구조가 복잡하거나 hierarchy가 높으면 좋지 않음
2. HAS-A 관계 ( composition )
- 클래스가 다른 클래스를 포함하는 관계 ( 변수로 선언 )
- 코드 재사용의 가장 일반적인 방법
- Student가 Subject를 포함하는
- Library를 구현할 때 ArrayList 생성하여 사용
- 상속하지 않음
06. 다운 캐스팅과 instanceof
1. 다운 캐스팅( downcasting )
: 업 캐스팅된 클래스를 다시 원래의타입으로 형 변환
: 하위 클래스의 형 변환은 명시적으로 해야함 ( 업캐스팅은 묵시적으로 일어남 )
Customer vc = new VIPCustomer(); //묵시적
VIPCustomer vCustomer = (VIPCustomer)vc; //명시적
2. instanceof를 이용한 인스턴스의 형 체크
: if 문을 이용하여 원래 인스턴스의 형이 맞는지 여부를 체크하는 키워드. 맞으면 true, 틀리면 false를 반환
if ( customerE instanceof GoldCustomer) { // 원래의 인스턴스 형이 맞는지 체크하는 것
GoldCustomer vc = (GoldCustomer) customerE; // 원래 골드인데 vip로 할수 없어서 에러 발생
System.out.println(customerE.showCustomerInfo());
다운캐스팅을 쓰면, 다시 되돌리는 것이고 코드가 복잡해지기 때문에, 가능하다면 오버라이딩으로 쓰는 것이 깔끔함.
하자만, 꼭 써야한다면 instanceof 로 꼭 확인 해야한다.