DAY 09
✏️ 상속
후손클래스가 선조클래스를 상속 받을 때 중요한 것
1. 선조가 가지고 있는 메소드, 멤버의 접근제한자
2. 선조의 생성자
상속을 받는다는 것은 선조가 가지고 있는 모든 기능 (메소드기능)을 내것처럼 호출 및 제어
✏️ overload & override
overload : 하나의 클래스에 같은 기능을 가지고 있는 메소드를 만들어서 괄호안의 매개인자나 데이터 타입을 다르게 주는 것
override : 선조도 있고 후손도 있는 상속 구조의 메소드
✍️ override (재정의)
//상속시 재정의 case 1
class My{
public void Prn(){
System.out.println("My`Prn");
}
}
public class Test extends My{
public void Disp() {
System.out.println("Test`Disp");
}
@Override
public void Prn() {
super.Prn();// 선조의 메소드를 명시적으로 호출해서 사용할 수 있다.
System.out.println("Test`Prn");
}
public static void main(String[] args) {
Test t1 = new Test();
t1.Prn(); // 재정의된 메소드가 호출된다.
t1.Disp();
}
//상속시 재정의 case2 -> Object class / API
public class Test01{ // extends class Test01 extends object{}
//모든 클래스는 단일 상속만이 가능하다.
//Object는 후손 클래스를 관리하는 메소드이다.
@Override
public String toString(){
return "Test01";
}
public static void main(String[] args){
Test01 t1 = new Test01();
//객체생성후 주소를 통해 t1을 호출하게 되면 선조의 toString()리턴
System.out.println (t1.toString());
System.out.println();
System.out.println(new Integer("100").toString());
System.out.println(new Integer("100"));
System.out.println(new Random());
// 난수를 발생하는 random함수는 toString 재정의 X
//모든 클래스가 toString을 재정의 하지는 않는다.
System.out.println(new Frame()); // component의 정보를 리턴
}
//상속시 재정의 case3 -> 익명형식
class MyTest{
public void Prn(){
System.out.println("MyTest");
}
}
public class Test02 {
public static void View(MyTest mt) {
mt.Prn();
}
public static void main(String[] args){
//MyTest m1 = new MyTest();
//View(m1);
View(new MyTest());
System.out.println();
View(new MyTest(){
@Override
public void Prn(){
System.out.println("마이 테스트야");
}
});
}
}
//상속시 재정의 case4 -> 익명형식 <<상속>>
class AA{
public void Prn_AA(){
System.out.println("Prn_AA");
}
}
class BB extends AA{
public void Prn_BB(){
System.out.println("Prn_BB");
}
}
public class Test03 {
public static void View (BB b1){
b1.prn_AA();
b1.Prn_BB();
}
public static void main(String[] args) {
View (new BB() {
@Override
public void Prn_BB(){
System.out.println ("쉬고싶다");
}
});
}
}
✍️ 추상화
- public abstract class userName{} => 추상클래스
- public abstract void Test (); => {}없이 선언되는 메소드는 추상 메소드
- 추상클래스를 상속받는 클래스는 추상클래스가 선언한 추상 메소드를 반드시 재정의 해야 한다.
- 만약에 재정의 하지 않으면 상속 받은 클래스는 추상 클래스가 된다. (객체 생성이 불가능하다)
- 추상클래스는 객체의 주소번지는 받을 수 있다.
- 추상클래스의 목적 : 강제 상속 , 강제 재정의
- 추상클래스는 추상메소드가 없어도 가능
상속구조의 주소 번지 활용
AA <- BB <- DD d1 = AA() <- BB() <- DD()
DD d1 = new DD();
- DD d1 = new BB(); -> X
=> 메모리에 2개를 만들었는데 3개 사용? 안된다.- BB b1 = new DD(); -> O
=> BB는 2개짜리 , DD는 3개짜리 -> 메모리는 3개 만들었지만 2개만 사용하겠다.- AA a1 = new BB(); -> O
=> 메모리상에 2개의 객체 생성 AA가 a1을 사용해서 하나만 사용하겠다
- 후손의 객체는 전체 대입이 가능하다.
AA a1 = new AA();
AA a1 = new BB();
AA a1 = new DD();
XX x1 = new ZZ();
=> x1.prn() 호출
=> ((ZZ)x1).setA(100); // 다운캐스팅
=> System.out.println(((ZZ)x1).getA());
- 선조의 주소를 받아서 값을 구현할 때 setA(),getA() 탐색할 수 없나??
=> 선조의 주소 번지를 이용해서 후손의 객체를 직접적으로 참조하지는 못해도 선조의 주소를 알고 있으면 후손을 타고 들어갈 수 있다 // 하위에 다운캐스팅
✍️ Interface
public interface IA{
public static final int k = 10;
int y = 20; // public static final int y = 20;
//추상메소드
public abstract void prn();
void disp(); // public abstract void disp();
//static
public static void static_prn() {
System.out.println("static_prn");
}
//default
public default void default_prn(){
System.out.println("default");
}
}
interface IB{
String test_prn(); //public abstract String test_prn();
}
✏️ 클래스 생성시 인터페이스 implements
public abstract class My implements IA,IB{
@Override
public void prn(){
}
@Override
public void disp(){
}
}