Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
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
Tags
more
Archives
Today
Total
관리 메뉴

우주코딩

다형성과 다형적 변수, 오버로딩과 상속, 오버라이딩과 필드 오버라이딩 본문

자바 본 강의

다형성과 다형적 변수, 오버로딩과 상속, 오버라이딩과 필드 오버라이딩

우주코딩 2021. 7. 30. 14:01

다형성 (polymorphism)

클래스 계층 구조를 알아야한다.
Vehicle
Car Bike
Sedan
Truck

레퍼런스는 같은 타입의 객체를 가리킬 수 있을 뿐만 아니라 그 클래스의 서브클래스 객체까지 가리킬 수 있다.

Vehicle vehicle = new Vehicle();
Bike bike = new Bike();
Car car = new Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();

Vehicle vehicle2 = null;
vehicle2 = bike; // OK
vehicle2 = car; //OK
vehicle2 = sedan; //OK
vehicle2 = truck; //OK

이렇게 상위 클래스의 레퍼런스로 하위 클래스의 인스턴스를 가리킬 수 있는 이유?
=> 하위 클래스의 인스턴스는 상위 클래스의 인스턴스 멤버를 갖고 있기 때문이다. (항상)
=> 그래서 상위 클래스의 레퍼런스로 그 클래스의 인스턴스 변수를 모두 사용할 수 있다.

이런 규칙에 따라, 다음 vehicle2 변수는 Vehicle 객체 뿐만아니라
Bike, Car, Sedan, Truck 객체까지 다양한 서브클래스의 객체를 가리킬 수 있다.
그래서 vehicle2를 "다형적 변수"의 기능을 갖고 있다 말한다.

다형적 변수 ( 다른 예시 )

Car obj;
obj = new Vehicle(); (X)
obj = new Bike(); (X)
obj = new Car(); (O)
obj = new Sedan(); (O)
obj = new Truck(); (O)

obj = 다형적 변수. 여러 인스턴스를 가리킬 수 있다. 단 규칙이 있다.
레퍼런스는 같은 타입의 객체 뿐만 아니라 하위 클래스의 인스턴스도 가리킬 수 있다.
하위 클래스가 인스턴스 멤버를 생성할 때 상위 클래스의 인스턴스 멤버도 생성하기 때문이다.

Bike bike = new Bike();

Vehicle vehicle = bike; //OK

이렇게 상위 클래스의 레퍼런스로 하위 클래스의 인스턴스를 가리킬 수 있다. 하위 클래스의 인스턴스는 상위 클래스의 인스턴스를 갖고 있기 때문이다.

상위클래스의 형변환

Bike bike = new Bike();
bike.model = a; // 가능
bike.capacity = b; // 가능
bike.engine = c; // 가능

Vehicle vehicle = new Bike();
vehicle.model = d; // 가능
vihicle.capacity = e; // 가능
vihicle.engine = f; // 불가
Car c = new Sedan();
c.cc = 1;
c.value =2;
c.model = 3;
c.capacity =4;
c.sunroof=5;    //컴파일 오류
c.auto = 6;   //컴파일 오류

비록 c가 가리키는 인스턴스가 Sedan이라고 할지라도 문법상 c는 Car의 레퍼런스이기 때문에 Car의 변수나 C의 수퍼클래스 변수만 사용할 수 있다.

컴파일러는 c변수에 어느 인스턴스가 들어있는지 실시간으로 검사를 하지 않는다.
레퍼런스의 타입에 한정하여 인스턴스나 클래스의 멤버 사용을 허락하여 문법에 맞게 작성했는지만 확인한다.

해결하기 위해서 레퍼런스 변수가 실제 가리키는 것이 무엇인지 알려주어야한다 -> 형변환
((원래인스턴스타입) 레퍼런스).멤버

((Sedan).c).sunroof = true;
((Sedan).c).auto = true;

또는 인스턴스의 원래 클래스 레퍼런스에 저장한 후 사용

Sedan s = (Sedan)c;
c.sunroof = true;
c.auto = true;

다형적 변수와 instanceof 연산자

  • instanceof는 레퍼런스에 들어있는 주소가 특정 클래스의 인스턴스인지 혹은 하위 클래스의 인스턴스인지 검사하는 연산자이다.
    특정 메소드 안에서 파라미터 변수의 인스턴스 주소가 어떤 클래스의 주소인지 판단해주는 역할을 할 수 있다.

overloading (더 싣다)

  • C언어는 다른 파라미터로 같은 함수를 수행하는 메서드들 모두 다른 이름으로 지어야한다.

  • 자바는 같은 일을 하는 수행하는 메서드를 같은 이름을 부여할 수 있도록 overload라는 문법을 만들었다.

  • 파라미터의 타입이나 개수가 다르더라도 같은 일을 하는 메서드에 대해 같은 이름을 갖게 할 수 있다.

  • 파라미터의 변수 이름으로 구분짓지 않는다. 메서드의 접근 범위는 상관없다.

  • 아규먼트의 타입이나 개수에 따라 호출되는 메서드가 결정된다. 따라서 프로그래밍의 일관성이 제공된다. ^^

오버로딩과 상속

부모 클래스인 A에 이미 m() 이라는 이름을 가진 메서드가 여러 개 있다.
그럼에도 불구하고 파라미터 형식이 다른 메서드를 추가한다면 이것도 마찬가지로 "오버로딩"이다.
즉 한 클래스 안에서 같은 이름의 메서드를 여러 개 만드는 것만 오버로딩이 아니다.
수퍼 클래스에 있는 메서드와 같은 이름을 가진 메서드를 추가해도 오버로딩이다.

물론 파라미터 형식은 달라야한다.
파라미터 형식까지 같으면 그건 overriding이다.

오버라이딩

  • 상속받은 메서드를 서브클래스의 역할에 맞게 재정의하는 문법

상속받은 메서드와 똑같은 메서드명, 파라미터 타입/개수/순서로 정의한다.
오버라이딩 메서드는 원래의 메서드 보다 접근 범위가 같거나 커야한다. 원래의 메서드보다 접근 범위가 줄어들면 안된다.

서브클래스의 역할에 맞는 메서드로 재정의하여 프로그래밍의 일관성을 확보한다.

필드 오버라이딩

필드 오버라이딩은 메서드와 달리 변수의 타입이 달라도 된다. 필드의 오버라이딩은 재정의가 아닌 새 필드를 추가한 것과 같다.

만약 수퍼클래스와 서브클래스가 같은 이름을 가진 인스턴스를 호출한다면 서브클래스에서 먼저 해당 필드를 찾는다. 따라서 수퍼클래스의 필드는 사용할 수 없게 된다.

가능한 수퍼클래스의 필드와 같은 이름을 가진 필드를 만들지 않는 것이 좋다.

Comments