클래스를 상속하여 정의해보자
사용할 수 있는 멤버들 확인 가능하다.
추가로 멤버들과 , 생성자를 추가해보자.
int turbo ;
String option ;
SportCar(){
System.out.println("====SportCar 기본 생성자");
}
SportCar(int turbo , String option){
this.turbo = turbo;
this.option = option;
System.out.println("====SportCar 현재 값 초기화 생성자");
}
tostring 도 함께 추가해 보자.
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString() //super 는 조상을 의미. 추가로 현재값을 넣어주기.
+"\n [ turbo = "+turbo+" , option : "+ option + " ]";
}
상속한 클래스를 사용해보자
상속한 클래스를 인스턴스 생성하여 사용해보자
조상과 현재 정의한 부분까지 사용할 수 있는 멤버들을 확인 해 볼 수 있다.
// 디폴트 생성자
SportCar sc1 = new SportCar();
System.out.println("main ) sc1 :"+sc1);
System.out.println();
sc1.brand = "apple"; //super 멤버변수 값.
sc1.grade='b'; // super 멤버변수 값.
sc1.option="navi"; // sub 멤버 변수 값.
System.out.println("main ) sc1 (초기화 3개 ):"+sc1);
super 란 부모 인스턴스를 지칭한다.
결과적으로 보면 Car 의 기본생성자 까지 실행 됬음을 알 수 있는데,
jvm 이 상속받은 클래스의 인스턴스를 생성하면서 , 상속받음을 확인하고 Car 를 실행한 후 SportCar를 실행하기 때문이다.
부모 메서드를 재정의 할 수 있다.
예를들어 부모에 hpowerUp 이라는 메서드가 있으면 ,
동일한 메서드명을 사용하며 오버라이딩을 정의해주고
원하는 메서드 동작을 설정하면 오버라이딩 할 수 있다.
// @Override
// public void hpowerUp() {
//
// super.hpowerUp();
// }
@Override
public void hpowerUp() {
speed+=100;
}
재 정의 한다는 것은 조상메서드 + 기능 추가 또는 새롭게 정의를 말하는 데 ,
위의 경우 새롭게 정의 했고 toString 같은경우 조상메서드에 + 기능 추가를 한 경우이다.
현재 값을 초기화 하는 경우 정의된 멤버들로 쉽게 this를 통하여 정의하면 되는데,
부모에 대한 값까지 정의하는 경우
super()를 사용한다면 , 부모 생성자를 호출할 수 있다.
즉 , 인자와 타입이 일치하는 경우 부모에서 정의한 초기화 생성자를 사용할 수 있다.
SportCar(int turbo , String option , double price , int speed , String brand , char grade ,String color){
super(price,speed,brand,grade,color);
// 부모의 생성자를 호출 . 인자의 순서와 갯수와 타입이 일치해야함.
//super.price = price ;
this.turbo = turbo;
this.option = option;
//super();
// 생략하면 컴파일러가 자동으로 조상의 기본 생성자를 넣어줌.
System.out.println("====SportCar 조상 값 + 현재 값 초기화 생성자");
}
부모에 생성메서드에서 초기화를 하지 않는 경우 super.price = price 처럼 접근해도 부모 멤버에 초기화가 가능하다.
부모의 생성자를 확인해보자.
// Class Car 의 모든 값 초기화 생성자
public Car(double price , int speed , String brand , char grade ,String color) {
this.price = price;
this.speed = speed;
this.brand = brand;
this.grade = grade;
this.color = color;
System.out.println("====Car의 모든 값 초기화 생성자");
}
만약 사용을 직접한다면 오버라이딩을 사용한 결과가 ,
Car 클래스의 생성자를 사용하였기 때문에 사용한 결과를 함께 볼 수 있다.
//Class Car 의 모든 값 초기화 생성자
//(int turbo , String option , double price , int speed , String brand , char grade ,String color)
SportCar sc3 = new SportCar(100 , "옵션" , 400.0 ,100, "브랜드" , 'A' , "컬러" );
System.out.println("main ) sc3 :"+sc3);
즉 , super() 는 조상 메서드를 의미하고,
super 은 조상 인스턴스를 의미하기 때문에
super.brand = brand ; 처럼 접근하여도 되지만,
생성자로 인한 접근이 아니기 때문에 public에 대한 멤버 접근만 가능할 것이다.
따라서 디폴트로 정의된 멤버는 접근할 수 없기 때문에 super()를 요긴하게 사용하는 것이 실수를 줄일 수 있을 것 같다.
자바의 생성 순서
JVM 은 extends 키워드가 있다면 조상 생성 후 후손을 생성한다.
이때 기본은 조상의 default 생성자를 생성하고 ,
특별히 후손 생성자에서 조상생성자(super())를 호출하면 그 생성자를 실행한다.
-> 상속을 허용하는 클래스는 default 생성자를 반드시 작성하는 것이 바람직하다.
각 클래스의 같은이름( numberOfLegs )의
instance 변수와 static 변수 보기
- 할아버지 (Animal) : numberOfLegs
- 아버지 (Mammal) :numberOfLegs
- 나 (Pet): numberOfLegs
- 나(Pet) 의 메서드의 지역변수(매개변수) : numberOfLegs
void legsPrint (int numberOfLegs) {
System.out.printf("Local(지역) = %d , 전역 = %d , parent(포유류) = %d , animal(할아버지) = %d %n",
numberOfLegs , this.numberOfLegs , super.numberOfLegs , Animal.numberOfLegs);
}
이 메서드를 보게되면 , 매개변수와 this 와 super 를 볼 수 있고 , static 으로 정의한 numberOfLegs를 볼 수 있다
pet2.legsPrint(10);
- mammal 에서의 아버지(Animal) static 변수에 접근하기.
상속의 경우 super. 접근하면 되지만 , static 변수는 static 변수답게 접근하라고 경고등이 뜬다
static은 클래스의 종속이기 때문에 Animal.numberOfLegs 로 접근해야한다
System.out.println("animal.numberOfLegs : "+Animal.numberOfLegs);
System.out.println("pet2.numberOfLegs :" +pet2.numberOfLegs );
값이 super를 타고 올라가서 , 값이 안착해 있음을 볼 수 있다.
static을 사용했을때의 초기화에서 주의해야 함을 알 수 있다.
static 메서드의 오버라이딩
//static 메서드의 오버라이딩
static void staticTest() {
System.out.println("Mammal의 static 테스트 메서드.");
}
void staticTest() {
System.out.println("Mammal의 static 테스트 메서드.");
} // static이 아니더라도 이름이 같으면 허용하지 않음.
static 메서드와 이름이 같은 noneStatic 메서드는 허용되지 않는다.
조상이 가지고 있다는 의미는 후손이 포함되기 때문이다.
그러나 오버로딩은 허용된다.
조상의 static메서드를 내부에서 사용하고 싶다면 static 하게 클래스를 호출할것.
* 정리
static 멤버들은 클래스의 종속임으로 상속의 개념보다 우선적용된다.
그러므로 오버라이딩은 적용되지 않고 각 클래스의 멤버가 된다.
즉 , 조상의 static 으로 정의된 staticTest()와 자손의 static 으로 정의된 staticTest()는 서로 무관하다.
상속받은 pet 에게 static 같은 이름의 메서드를 사용하면 , 오버라이딩은 아니고,
독립적인 pet의 static 메서드가 형성된 것이다.
그러므로 , 상속과 무관하게 어디서든 클래스명으로 접근이 가능하다.
static 메서드는 this , super 사용금지 (인스턴스를 지칭하기 때문)
super는 인스턴스를 의미하기 때문에 접근할 때 정적멤버인지 비정적멤버인지 확인하고 쓸것.
사용할때는 static 답게 접근할 것.
pet2.staticTest(); //경고
Pet.staticTest(); // 이렇게 사용
'Developer > JAVA' 카테고리의 다른 글
JAVA , 추상 클래스 (0) | 2024.08.08 |
---|---|
JAVA , 클래스의 다형성, 타입 캐스팅(형변환) , 종단 클래스 (0) | 2024.08.07 |
JAVA , 클래스간의 관계 : use , has, is (0) | 2024.08.06 |
JAVA , 예제 : 로또 번호 생성기 , 학생 성적순 출력 (0) | 2024.08.06 |
JAVA , 접근 제어자 : 설정자와 접근자 (0) | 2024.08.05 |