41기 개발자과정

20211206 상속, 다형성

segment 2021. 12. 6. 23:52

상속


 클래스를 확장한다 -> 확장시킬 대상을 상속하여 확장한다.
  - 확장된 클래스는 상속받은 클래스 멤버를 가지고 있다.


 - 상속한 클래스 -> 슈퍼 클래스
 - 상속받은 클래스 -> 서브 클래스.
 - 상속받은 클래스(서브 클래스)가 객체화시, 슈퍼클래스가 먼저 객체화가 되어야 한다.
 - 슈퍼클래스 추상적인 클래스어야 한다.

 

 - 상속 방법 : class 클래스(자식) extends 클래스(부모)

 

 

//슈퍼클래스
class User2{
	public User2(){
		System.out.println("슈퍼클래스 생성자 메서드 호출");
	}
	private String userName;
	private int userAge;
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public int getUserAge() {
		return userAge;
	}
	public void setUserAge(int userAge) {
		this.userAge = userAge;
	}
	
}

 

Student 클래스는 User2 클래스를 상속받는다. 

//서브 클래스
class Student extends User2{
	public Student() {
		System.out.println("서브클래스 생성자 메서드 호출");
	}
}

 

콘솔창 :  1. 슈퍼클래스 콘솔창 출력 -> 2. 서브클래스 콘솔창 출력

슈퍼클래스의 생성자가 먼저 실행된다.

서브 클래스의 생성자 호출에 앞서

슈퍼 클래스의 생성자가 호출된다

 


Student 클래스는 User2 클래스를 포함하고 있다

 

서브 클래스가 객체화시 참조타입으로 슈퍼클래스 타입이 올 수 있다.

Student st = new Student();
st.setUserAge(20);
st.setUserName("홍길동");

 

상속관계를 가진 대상끼리 업캐스팅과 다운캐스팅이 가능하다.

User2 us2 = st; // 업캐스팅
Student st2 = (Student) us2; // 다운 캐스팅

 

User2가 객체화시 Student 를 가지고 있지 않으므로 캐스팅이 불가능하다.
즉 캐스팅이 원활하게 되어야 한다면 
캐스팅 될 대상은 모두 객체화가 되어야 캐스팅이 가능하다.

 

 

1) 형변환 기호 생략 불가능

2) 업캐스팅이 선행되지 않을 경우 에러 발생.

자식클래스 참조변수 = (자식클래스) new 부모클래스();

User2 us3 = new User2();
Student st3 = (Student) us3; // 다운 캐스팅

class SuperA{
	String superNameA;
	public SuperA() {
		System.out.println("superA  생성자 메서드");
	}
}
class SuperB extends SuperA{
	String superNameB;
	public SuperB() {
		System.out.println("SuperB 생성자 메서드");
	}
}
class Sub extends SuperB{
	String subName;
	public Sub() {
		System.out.println("Sub 생성자 메서드");
	}
}

 

1)

s 식별자에 객체 주소가 저장(슈퍼 클래스 객체 주소도 포함)

Sub s = new Sub();

서브클래스는 슈퍼클래스의 멤버에 접근이 가능하다.

s.subName = "subName";
s.superNameA = "superA";
s.superNameB = "superB";

 

2)

서브클래스가 객체화 되었더라도 참조타입에 의한 멤버만 접근이 가능하다.
슈퍼클래스 참조타입에서 서브클래스 멤버로 접근은 불가능하다.

sb.subName 에는 접근이 불가능하다.

SuperB sb = s; 
System.out.println(sb.superNameA+"/"+sb.superNameB);
sb.superNameA = "superAA";
sb.superNameB = "superBB";

 

캐스팅이 되었더라도 실체 객체화된 대상은 사라지지 않았다.

SuperA sa = sb;
System.out.println(sa.superNameA);
sa.superNameA = "superAAA";

 

객체의 주소가 변화한 것은 아니므로, 위에서 저장한 데이터값이 그대로 출력

Sub s2 = (Sub) sa;
System.out.println(s2.subName);
System.out.println(s2.superNameA);
System.out.println(s2.superNameB);

 

하나의 참조타입으로 공통 코드 작성
다형성 
- 하나의 참조타입으로 여러객체를 참조할 수 있다.

 

상속을 사용하는 이유 : 

슈퍼 클래스 참조 타입으로 공통 비즈니스 로직 작성
모듈이 달라도 슈퍼클래스 타입으로 공통 로직을 진행할 수 있다.

 


실습.

package kr.or.ksmart;

class MySumNumber{
	private int n1;
	private int n2;
	public int getN1() {
		return n1;
	}
	public void setN1(int n1) {
		this.n1 = n1;
	}
	public int getN2() {
		return n2;
	}
	public void setN2(int n2) {
		this.n2 = n2;
	}
	
}
class MySum{
	public void sum(MySumNumber sum) {
		System.out.println();
	}
}

class MySumNum1 extends MySumNumber{}
class MySumNum2 extends MySumNumber{}

public class javaBasicEx03 {

	public static void main(String[] args) {
		/*
		 * 실습. 아래의 코드의 에러를 해결하도록 하여라.
		 * */
		MySumNumber num1 = new MySumNum1();
		num1.setN1(10);
		num1.setN2(30);
		MySumNumber num2 = new MySumNum2();
		num2.setN1(20);
		num2.setN2(30);
		MySum m = new MySum();
		m.sum(num1);
		m.sum(num2);

	}

}

 

 


개념 재정리하기.

 

https://youtu.be/Pgutf0G3nE4

 

상속 :

- 기존의 클래스로 새로운 클래스를 작성하는 것 (코드의 재사용)

- 두 클래스를 부모와 자식으로 관계를 맺어주는 것

class 자식클래스 extends 부모클래스 {}

- 자손은 조상의 모든 멤버를 상속받는다. (생성자, 초기화 블럭 제외)

- 조상 : 부모의 부모~ 까지 포함한다.

- 자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다)

child 클래스는 멤버가 0개 아니다. 1개를 상속받고 있기 때문에 멤버는 1개이다.

 

- 자손의 변경은 조상에 영향을 미치지 않는다.

부모 : 멤버1개 / 자식 : 자신의 멤버 1개 + 상속받은 멤버 1개 = 멤버 2개

 

실습1.

1) 2차원 좌표 클래스

class point{
	int x;
    int y;
}

2-1) 3차원 좌표 - z가 추가 되었다.

class Point3D{
	int x;
    int y;
    int z;
}

2-2) Point 클래스를 상속받는 Point3D 로 다시 정의해주기.

public Point3D extends Point{
	int z;
}

 

3) 객체를 생성했을 때 data 영역은? 

- 2-1 과 2-2 는 같다!

Point3D p = new Point3D();

 

 

포함이란?

- 클래스의 멤버로 참조변수를 선언하는 것

- 작은 단위의 클래스를 만들고, 이들을 조합해서 클래스를 만든다.

---> 객체화 했을 경우

1번 2번
x값 : c.x
y값 : c.y
x 값: c.c.x
y값 : c.c.y

 

캡슐화

접근제어자를 사용하는 이유?

- 외부로부터 데이터를 보호하기 위해서

- 내부적으로만 사용되는 부분을 감추기 위해서

 

 

다형성

- 여러가지 형태를 가질 수 있는 능력

- 조상타입 참조변수로 자손타입 객체를 다루는 것

- 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.

 

---> 큰 개념에는 작은 개념을 넣을 수 있지만, 작은 개념에는 큰 개념을 넣을 수 없다.

 

 

1) 

 

---> 오버라이딩된 call 메서드만 호출 가능하다!

 

 

 

2)