멤버변수 이름 앞에 명시
-> 부모 클래스의 멤버변수를 의미한다. 하지만 부모클래스의 멤버변수는
이미 모두 상속되어 있기 때문에 이 경우에는 this 키워드를 사용하는
것과 동일한 결과이기에 잘 사용하지 않는다.
메서드 이름 앞에 명시
-> 부모 클래스의 메서드를 의미한다.
-> 재정의 되지 않은 메서드 : 이미 상속되어 있기 때문에 this 키워드를
사용하는 것과 동일한 결과를 갖는다.
-> 재정의된 메서드 : Override 된 메서드 이름 앞에 사용하게 되면
재정의 되기 이전의 원본 메서드를 의미한다.
키워드 자체를 메서드처럼 사용
-> 부모 클래스의 생성자를 의미한다.
super(2/4) 설명
-> Hello 클래스가 Korean에 상속되고, Korean클래스가 say() 메서드를
Override 처리하게 되면 Korean 클래스의 객체는 더 이상 부모의
say() 메서드에 접근할 수 없게 된다.
super(3/4) 설명
-> 만약 부모 클래스가 가지고 있는 say()메서드에 추가적인 기능을
구현하고자 한다면 부모의 코드를 그대로 복사해서 사용해야 할 것이다
원본 기능에 대한 수정이 발생할 경우 부모 클래스와 자식 클래스를
모두 수정해야 하기 때문에 소스코드의 유지보수 효율성이
떨어지게 된다.
super(4/4) 설명
-> super 키워드는 부모 클래스의 메서드를 호출하는 기능을 가지고
있기 때문에, Override된 자식 클래스의 메서드에서 super 키워드를
사용하면, 재정의 되기 이전의 부모 클래스에 대한 메서드를
호출할 수 있다.
package casting;
public class AirForce extends Unit {
public AirForce (String name) {
super (name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 이륙");
System.out.println(this.getName() + ">> 공중공격 실행");
}
public void bombing() {
System.out.println(this.getName() + ">> 폭격");
}
}
package casting;
public class Army extends Unit {
public Army(String name) {
super(name);
}
// Override 메서드
// 공격의 형태를 육군에 맞게 변경하지만, 부모 클래스가 가지고 있는 공격 준비
// 기능을 super 키워드를 재사용해서 호출하려고함
@Override
public void attack() {
super.attack();
System.out.println(super.getName() + ">> 지상공격 실행함");
}
public void tank() {
System.out.println(super.getName() + " >>탱크 공격");
}
}
package casting;
public class Navy extends Unit {
public Navy (String name) {
super(name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 해상공격 실행함");
System.out.println(this.getName() + ">> 지상 상륙");
}
public void nucleus() {
System.out.println(this.getName() + ">> 핵미사일");
}
}
package casting;
public class Unit {
private String name;
public Unit(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void attack() {
System.out.println(this.name + ">>> 공격준비");
}
}
package casting;
public class Main02 {
public static void main(String[] args) {
AirForce af = new AirForce("공군");
Navy nv = new Navy("해군");
Army am = new Army("육군");
// 각각의 객체는 자신들의 고유 기능을 사용할 수 있다.
af.bombing();
nv.nucleus();
am.tank();
System.out.println("-------------------");
// 암묵적 형변환
Unit temp1 = af;
Unit temp2 = nv;
Unit temp3 = am;
//형변환이 되더라도 상속받거나 재정의한(Override) 자신들의 기본 특성은 그대로 유지함
temp1.attack();
temp2.attack();
temp3.attack();
// 상위 클래스 형태로 형변환이 되면, 자신들의 독립 기능은 사용하지 못함
// temp1.bombing();
// temp2.nucleus();
// temp3.tank();
System.out.println("-------------------------");
// 원래의 기능을 되돌리기 위해서는 하위 클래스 형태로 명시적 형변환이 필요
AirForce re1 = (AirForce)temp1;
Navy re2 = (Navy)temp2;
Army re3 = (Army)temp3;
re1.bombing();
re2.nucleus();
re3.tank();
}
}
메서드간의 파라미터가 서로 달라야한다.
-> 파라미터의 데이터 타입이 다르다.
( 데이터 형이 동일하고 변수의 이름이 다른경우는 동일한 파라미터로 인식된다)
-> 파라미터의 개수가 다르다.
-> 서로 다른 데이터형을 갖는 파라미터들의 전달 순서가 다르다.
리터형이 다른 경우는 오버로드의 성립에 아무런 영향을 주지 않는다.
파라미터의 데이터형이 서로 다르기 때문에 오버로드 성립
public void user(int a){ .. }
public void user(long a){ .. }
파라미터의 개수가 서로 다르기 때문에 오버로드 성립
public void user( int a ){..}
public void user( int a, int b ){..}
데이터 형의 전달 순서가 서로 다르기 때문에 오버로드 성립
public void user(int a, String b){..}
public void user(String b, int a ){..}
오버로드 성립 불가
public void user(int a, String b){...}
public void user(int b, String a){...}
package override;
public class AirForce extends Unit {
public AirForce (String name) {
super (name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 이륙");
System.out.println(this.getName() + ">> 공중공격 실행");
}
public void bombing() {
System.out.println(this.getName() + ">> 폭격");
}
}
package override;
public class Army extends Unit {
public Army(String name) {
super(name);
}
// Override 메서드
// 공격의 형태를 육군에 맞게 변경하지만, 부모 클래스가 가지고 있는 공격 준비
// 기능을 super 키워드를 재사용해서 호출하려고함
@Override
public void attack() {
super.attack();
System.out.println(super.getName() + ">> 지상공격 실행함");
}
public void tank() {
System.out.println(super.getName() + " >>탱크 공격");
}
}
package override;
public class Navy extends Unit {
public Navy (String name) {
super(name);
}
public void attack() {
super.attack();
System.out.println(this.getName() + ">> 해상공격 실행함");
System.out.println(this.getName() + ">> 지상 상륙");
}
public void nucleus() {
System.out.println(this.getName() + ">> 핵미사일");
}
}
package override;
public class Unit {
private String name;
public Unit(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void attack() {
System.out.println(this.name + ">>> 공격준비");
}
}
package override;
class Hello{
public void say() {
System.out.println("Hello");
}
}
class Korean extends Hello{
//korean 클래스에 의해 say() 메서드가 Override된 경우
public void say () {
System.out.println("안녕하세요");
}
public void sayHello() {
super.say(); // 부모 클래스(Hello)의 say()
this.say(); // 나 자신(Korean)의 say()
}
}
public class Main01 {
public static void main(String[] args) {
Korean kor = new Korean();
kor.sayHello();
System.out.println("------------------------");
kor.say();
}
}
package override;
public class Main03 {
public static void main(String[] args) {
Army am = new Army("육군");
Navy nv = new Navy("해군");
AirForce af = new AirForce("공군");
am.attack();
am.tank();
nv.attack();
nv.nucleus();
af.attack();
af.bombing();
}
}
java 기본 유형의 데이터들처럼 객체 참조변수의 경우에도 형변환(casting)이
이루어 진다.
서로 다른 클래스 유형으로부터 나온 객체 참조변수들 간의 대입에는
일정한 규칙이 있다.
Parent parent = new Child();
왼쪽 항(부모 클래스)과 오른쪽 항(자식 클래스)의 객체 유형이 서로 다른 경우,
두 유형이 서로 상속 관계에 있고 왼쪽 객체(부모 클래스)가 오른쪽 객체(자식클래스)
의 상위 클래스인 경우에만 암묵적 형변환이 일어난다.
하위 클래스에서 상위클래스 유형으로 항당하는 것은 가능하나 그 반대의 경우에는
명시적 형변환을 해야한다.
-> 그러나 상위 클래스 유형을 하위 클래스 유형으로 강제 형 변환하는
경우에는 할당되는 객체의 유형에 따라서 실행 오류가 발생할 수 있다.
A a1 = new B();
A a2 = new X();
A a3 = new C();
A a4 = new Y();
B b1 = new C();
X x1 = new Y();
C c = new C();
B b2 = c;
Y y = new Y();
X x2 = y;
암묵적 형변환은 부모를 상속받는 자식객체의 기능을 부모에게
물려받은기능만 사용하도록 제한한다.
그러므로 암묵적 형변환이 발생하게 되면 오버라이드된 기능만 사용가능
하고, 추가적으로 구현한 기능은 사용할 수 없다.
주의할 점은 기능의 제한이지 기능의 변경은 아니다.
Unit u1 = new Army();
Unit u2 = new Navy();
Unit u3 = new AirForce();
u1.attack();
u2.attack();
u3.attack();
상속관계의 객체를 부모형태로 변환하면 클래스의 종류를 구분하지 않고
일관된 기능을 호출할 수 있다.
객체가 상위클래스형태로 형변환 되더라도 Override된 자신의 기능은
잃지 않는다.
하지만, 추가적으로 구현했던 기능은 사용할 수 없게 되므로
원래의 기능을 다시 사용할 수 있는 방법이 필요해졌다.
부모 클래스의 객체를 자식 클래스 형태로 변환하는 것
형변환을 위해서는 변환할 클래스 이름을 명시적으로 지정해 주어야 한다.
ChildClass child = (ChildClass)parent;
ChildClass child1 = new ChildClass();
ParentClass parent = child1; // 암묵적 형변환
ChildClass child2 = (ChildClass)parent;
Army army1 = new Army();
Unit u = army1;
Army army2 = (Army)u;
--------------
Unit u = new Navy();
Navy navy = (Navy)u;
-------------------------------
=> 위의 두 경우 모두 문법적인 오류는 없기 때문에,
이클립스에서는 에러를 검출하지 못한다. 하지만 프로그램을 실행
시켰을 경우에는 에러가 발생한다.