728x90

super는 부모, sub는 자식을 뜻한다.
상속을 사용하는 이유는 이미 만들어진 클래스에서 좀더 업그레이드를 시키기위해 기존의 메소드와 필드를 업혀서 기능들을 더 추가하기위한 방법이다.

상속의 장점!

1. 코드를 재활용함으로써 클래스 구조가 간결해진다
2. 상속을 하면 부모클래스안의 메소드만 확인하면 나머지도 잘 되는 거니깐 정확성이 높아진다.
3. 부모클래스에 몇개가 모여져 있으니까 수정/추가에 대한 유연성 및 확장성이 증가한다.

 

부모클래스는 자기 껏만 사용할 수 있는데 
부모클래스를 상속받는 자식클래스는 자기것만 아니라 부모것도 자동으로 사용할 수있다.

하나의 부모가 여러 자식에게 상속 가능 자식이 여러 부모의 상속불가능

private는 그 클래스 안에서만 접근이 가능한데
protected는 상속받는 자식 클래스까지 접근이 가능하다.

package inheritance;

public class SuperTest {

protected double weight;
protected double height;

public SuperTest(double w, double h) {
   this.weight = w;
   this.height = h;
}
public void disp() {
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}

package inheritance;

public class SubTest extends SuperTest{
  
   public static void main(String[] args) {
     }
}
   

부모클래스에 weight와 height를 필드로 선언하고 
파라미터값을 받는 생성자를 만들고
출력하는 disp()를 만들었다.  
근데 이렇게 하면 자식클래스에 밑줄친것 처럼 오류가 나타난다.

왜냐하면 부모클래스에서 '기본생성자'를 만들지 않았기 때문이다.
부모클래스는 문제없는데 자식클래스는 자기꺼+부모꺼 까지 생성자를 구분한다.
자바는 생성자를 만들지 않으면 자동으로 '기본생성자'를 생성한다.(우리눈에 안보여도 생성된다)
근데 다른 생성자를 만들면 '기본생성자'를 만들어주지않는다. 우리가 직접 선언을 해줘야 한다.

그래서 오류가 나는 이유는
부모클래스에서 파라미터값을 받는 생성자(public SuperTest(double w, double h))를 만들었기 때문에
'기본생성자'가 자동으로 생성되지 않았다. 그래서 SubTest클래스에선 자기는 기본생성자가 자동으로 생성되었는데 부모인SuperTest에는 기본생성자가 없네? 하면서 오류가 나는 것이다.
아래 처럼 부모클래스에도 기본 생성자를 만들면 오류는 해결된다.

package inheritance; 

public class SuperTest { 

protected double weight; 
protected double height;

public SuperTest() {
   System.out.println("SuperTest 기본 생성자");
}
public SuperTest(double w, double h) {
   this.weight = w;
this.height = h;
}
public void disp() {
   System.out.println("SuperTest클래스의 disp()");
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}
package inheritance; 

public class SubTest extends SuperTest{ 

   public static void main(String[] args) { 
      }
}
     

package inheritance; 

public class SuperTest { 

protected double weight; 
protected double height;

public SuperTest() {
   System.out.println("SuperTest 기본 생성자");
}
public SuperTest(double w, double h) {
   this.weight = w;
this.height = h;
}
public void disp() {
   System.out.println("SuperTest클래스의 disp()");
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}
package inheritance; 

public class SubTest extends SuperTest{ 

 public SubTest() { 
          System.out.println("SubTest 기본 생성자")
     }

   public static void main(String[] args) { 
      SuperTest aa = new SuperTest();
//부모클래스를 그냥 사용사능
     System.out.println();
     SubTest bb = new SubTest(); 

     }

자식(SubTest)클래스에 노란색처럼 기본생성자를 넣어주고
new생성자를 이용하면 각 클래스의 기본생성자가 출력이 된다.

SuperTest 기본 생성자

SuperTest 기본 생성자
SubTest 기본 생성자

자식클래스에 선언한 SuperTest aa = new SuperTest(); 때문에 부모클래스의 기본 생성자가 나오고
SuperTest aa = new SuperTest(); 자기를 생성자로 만들면 
자식은 부모것도 자기것이기 때문에 부모클래스와 자식 클래스의 기본생성자 두개가 출력된다. 
자식은 별다른명령어 없이도 부모클래스의 필드나 메서드를 마음대로 호출할 수 있다.

 


package inheritance; 

public class SuperTest { 

protected double weight; 
protected double height;

public SuperTest() {
   System.out.println("SuperTest 기본 생성자");
}
public SuperTest(double w, double h) {
   this.weight = w;
this.height = h;
}
public void disp() {
   System.out.println("SuperTest클래스의 disp()");
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}
package inheritance; 

public class SubTest extends SuperTest{ 

   protected String name;
   protected int age;

 public SubTest() { 
          System.out.println("SubTest 기본 생성자")
     }

   public static void main(String[] args) { 
     SuperTest aa = new SuperTest();
//부모클래스를 그냥 사용사능
     System.out.println();
     SubTest bb = new SubTest(); 
     }

위에 노란색처럼 필드를 추가해주자
그럼 부모클래스의 필드는 weight, height 2개인데
자식클래스의 필드는 부모의 필드를 받고 지것도 해서 weight, height, name, age 총 4개가 된다.


package inheritance; 

public class SuperTest { 

protected double weight; 
protected double height;

public SuperTest() {
   System.out.println("SuperTest 기본 생성자");
}
public SuperTest(double w, double h) {
   this.weight = w;
this.height = h;
}
public void disp() {
   System.out.println("SuperTest클래스의 disp()");
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}
package inheritance; 

public class SubTest extends SuperTest{ 

   protected String name;
   protected int age;

 public SubTest() { 
          System.out.println("SubTest 기본 생성자")
     }
   public SubTest(double weight, double height, String              name, int age) {
          System.out.println("SubTest 생성자");
          super.weight = weight;
          this.height = height;
          this.name = name;
          this.age = age;
    }
   public void output() {
          System.out.println("몸무게: "+weight);
          System.out.println("키: "+height);
          System.out.println("이름: "+name);
          System.out.println("나이: "+age);

   }

   public static void main(String[] args) { 
     SuperTest aa = new SuperTest();
//부모클래스를 그냥 사용사능
     System.out.println();
     SubTest bb = new SubTest(); 
     }

노란색부분은 파라미터를 받는 생성자를 추가하고 
주황색부분은 출력하는 메소드를 만들었다.

노란색부분에서 super와 this를 썼는데 super는 부모를 뜻하고 this는 자기(자식클래스)를 뜻한다.
근데 weight는 부모클래스에 있는 필드니까 super.를 사용했는데 height는 this를 썼다? 
자식은 부모껀 내껀데? 하는 느낌이라서 부모클래스의 필드도 지께되서 this를 사용해도 상관이 없다.....
그러나 알아보기 편하게 부모껀 super로 하자.

주황색부분도 마찬가지이다. 출력하는데 다른거 같으면 weight나 height에 super나 다른클래스를 불러오는 뭔가를 해줘야 하는데 자식은 부모것을 다 쓸수있으니깐 그냥 써도 자동으로 인식이되어 오류가 나지 않는다. 
super.weight를 써도 된다.


package inheritance; 

public class SuperTest { 

protected double weight; 
protected double height;

public SuperTest() {
   System.out.println("SuperTest 기본 생성자");
}
public SuperTest(double w, double h) {
   this.weight = w;
this.height = h;
}
public void disp() {
   System.out.println("SuperTest클래스의 disp()");
   System.out.println("몸무게= "+weight);
   System.out.println("키= "+height);
}
package inheritance; 

public class SubTest extends SuperTest{ 

   protected String name;
   protected int age;

 public SubTest() { 
          System.out.println("SubTest 기본 생성자")
     }
   public SubTest(double weight, double height, String              name, int age) {
          System.out.println("SubTest 생성자");
          super.weight = weight;
          this.height = height;
          this.name = name;
          this.age = age;
    }
   public void output() {
          System.out.println("몸무게: "+weight);
          System.out.println("키: "+height);
          System.out.println("이름: "+name);
          System.out.println("나이: "+age);

   }

   public static void main(String[] args) { 
     SuperTest aa = new SuperTest();
//부모클래스를 그냥 사용사능
     System.out.println();
    SubTest bb = new SubTest(75.3, 185.5, "홍길동",25); 
    //파라미터 값을 넣고
bb.output(); 
//먼저 SubTest클래스에서 찾고 없으면 SuperTest클래스로 넘어간다.
System.out.println();
bb.disp();
//먼저 SubTest클래스에서 찾고 없으면 SuperTest클래스로 넘어간다.


     }
}

SuperTest 기본 생성자

SuperTest 기본 생성자
SubTest 생성자
몸무게: 75.3
키: 185.5
이름: 홍길동
나이: 25

SuperTest클래스의 disp()
몸무게= 75.3
키= 185.5

자식클래스에 있는 output()를 사용해 정보를 출력하고
bb.disp();를 하면 SubTest bb = new SubTest(75.3, 185.5, "홍길동",25); 에 있는 파라미터 값들이 
부모클래스에 있는 disp()를 찾아가 weight와 height를 출력하게 된다.

 


this()나 super()는 static영역에서는 사용할 수 없다. 그래서 지금까지 공부한 것을 보면 메인영역에는 this나 super를 사용하지 않았다.
메인영역 밖에서도 클래스 영역중에 ststic를 사용하지 않은 곳에만 this, super를 사용할 수  있다. 그래서 자식클래스의 메인 메소드안에서 바로 super.부모클래스의 메서드를 할 수없다.

 

그리고 메소드를 오버라이드하면 부모의 메소드는 무시하고 무.조.건. 오버라이드된 자식클래스내의 메소드에서 작동한다.
메소드명만 같고 파라이터가 다르면 오버로드
메소드명이 같고 파라미터도 같으면 오버라이드



내가 알아보기 쉽게 정리!

부모(Super)클래스

package com.zoo;

public class A {
	protected int a = 1;
	protected String oh = "A클래스의 oh";
	
	public void play() {
		System.out.println("클래스A의 play");
	}

}

자식(Sub)클래스

ckage com.zoo;

public class B extends A{
	
		int a1 = 2;
		String oh1 = "B클래스의 oh";
		
		public void play() {
			System.out.println("클래스B의 play");
		}
	

}

메인클래스

package com.zoo;
//상속 완전 정리
public class C {
	public static void main(String[] args) {
		System.out.println("A aClass = new A(); 일때");
		A aClass = new A();
		System.out.println("Super클래스인 A클래스의 변수a : "+aClass.a);
		System.out.println("Super클래스인 A클래스의 변수oh : "+aClass.oh);
		aClass.play();
		System.out.println();
		
		System.out.println("B bClass = new B(); 일때");
		B bClass = new B();
		System.out.println("Super클래스인 A클래스의 변수a : "+bClass.a);
		System.out.println("Sub클래스인 B클래스의 변수a : "+bClass.a1);
		System.out.println("Super클래스인 A클래스의 변수oh : "+bClass.oh);
		System.out.println("Sub클래스인 B클래스의 변수oh : "+bClass.oh1);
		bClass.play();
		System.out.println();
		
		System.out.println("A aClass = new B(); 일때");
		A abClass = new B();
		System.out.println("Super클래스인 A클래스의 변수a : "+abClass.a);
		System.out.println("Super클래스인 A클래스의 변수oh : "+abClass.oh);
		abClass.play();
		
		
		
		
	}

}

결과

A aClass = new A(); 일때
Super클래스인 A클래스의 변수a : 1
Super클래스인 A클래스의 변수oh : A클래스의 oh
클래스A의 play

B bClass = new B(); 일때
Super클래스인 A클래스의 변수a : 1
Sub클래스인 B클래스의 변수a : 2
Super클래스인 A클래스의 변수oh : A클래스의 oh
Sub클래스인 B클래스의 변수oh : B클래스의 oh
클래스B의 play

A aClass = new B(); 일때
Super클래스인 A클래스의 변수a : 1
Super클래스인 A클래스의 변수oh : A클래스의 oh
클래스B의 play

ㅇ필드는 각자의 꺼를 사용하지만 메소드는 오버라이딩이 되어 부모와 자식의 메소드중에 자식의 메소드를 우선 적용한다.

 

728x90

'JAVA' 카테고리의 다른 글

Import Static  (0) 2020.09.28
배열 연습문제 05  (0) 2020.09.24
ArrayList  (0) 2020.09.21
set, get 메소드를 사용하는 이유  (0) 2020.09.17
[메소드]toString()메소드  (0) 2020.09.16

+ Recent posts