상속
- 상속이란, 기존의 클래스(부모클래스)를 재사용해서 새로운 클래스(자식클래스)를 작성하는 것
- 상속을 이용해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있다
- 새로 작성된 클래스들은 기존 클래스의 코드로 공통으로 가지게 되기 때문에, 공통코드의 관리가 쉬워짐
상속의 장점
- 코드의 재사용성을 높일수 있다.
- 코드의 중복을 제거할 수 있다
- 프로그램의 생산성과 유지보수성이 좋아진다
상속을 이용해서 새로운 클래스 작성하기
public class Phone {
String number;
public void call() {
System.out.println("전화를 건다");
}
public void receive() {
System.out.println("전화를 받는다");
}
}
위처럼 Phone 객체를 만들고 Phone객체를 상속하는 SmartPhone 객체를 만들 경우에
extends 키워드를 사용하면 된다
(기존 클래스[부모클래스]를 상속받아서 새로운 클래스[자식클래스] 작성할 때는 extends를 붙여야 한다)
public class SmartPhone extends Phone {
String ip;
public void internet() {
System.out.println("인터넷을 이용합니다");
}
public void game() {
System.out.println("게임을 합니다");
}
}
상속을 받게 될 경우
- 하위클래스는 상위 클래스의 멤버와 메소드를 상속받는다
- 하위클래스는 추가적인 코드 작성 없이 상위클래스로부터 상속받은 멤버와 메소드를 바로 사용할 수 있다
- 동일한 상위클래스를 상속받아서 만들어진 하위 클래스는 상위클래스로부터 상속받은 필드와 메소드가 동일하다
- 각각의 하위클래스에서 필드와 메소드를 추가할 수 있다
상속관계에 있는 객체의 생성
- 하위 객체를 생성하면 상위객체도 같이 생성된다
- 하위 객체는 상속받은 상위 객체를 포함하고 있다
- 하위 객체를 참조하는 참조변수로 하위 객체의 변수와 메소드를 사용할 수 있다 ( 상속받은 상위 객체의 변수와 메소드도 사용할 수 있다)
- 동일한 상위 클래스를 상속받은 모든 하위클래스는 객체를 생성하면 모두 상위 객체를 내부에 포함하게 된다
Java에서는 단일상속만을 지원한다
- 하위 클래스는 한 개의 상위 클래스만 상속받을 수 있다
- 두 개 이상의 상위 클래스를 동시에 상속받을 수 없다
// 오류가 발생한다
// 하위 클래스는 오직 상위 클래스 하나만 상속받을 수 있다.
public class Child extends Parent1, Parent2 {
}
- 동시에 상위 클래스를 두개 상속받을 수는 없지만, 여러 상위 클래스를 수직적으로 상속받을 수는 있다
// GrandParent 클래스
public class GrandParent {
// GrandParent 클래스의 멤버, 메소드
}
// GrandParent 클래스를 상속받은 Parent 클래스
public class Parent extends GrandParent {
// Parent 클래스의 멤버, 메소드
}
public class Me extends Parent {
// Me 클래스의 멤버, 메소드
}
상속관계에 대한 예제
public class Phone {
String number;
public void call() {
System.out.println("전화를 건다");
}
public void receive() {
System.out.println("전화를 받는다");
}
}
public class SmartPhone extends Phone {
String ip;
public void internet() {
System.out.println("인터넷을 이용합니다");
}
public void game() {
System.out.println("게임을 합니다");
}
}
public class Iphone extends SmartPhone {
public void appleMusic() {
System.out.println("애플뮤직을 실행합니다");
}
public void applePay() {
System.out.println("애플페이로 결제합니다");
}
}
public class Android extends SmartPhone {
public void youtube() {
System.out.println("유튜브를 봅니다");
}
public void recoding() {
System.out.println("통화를 녹음합니다");
}
}
위 코드는 Phone 객체가 존재하고, Phone 객체를 상속받은 SmartPhone객체
그리고 SmartPhone을 상속받은 Iphone 객체와 Android 객체가 존재한다.
위 그림을 보면 코드보단 한눈에 보기 쉬울것이다.
Object
- 상위클래스가 지정되지 않은 클래스는 항상 Object 클래스를 상속받는다
- Object 클래스는 자바의 최상위 클래스다 ( Object 클래스는 상위 클래스가 없는 유일한 클래스다 )
- Object 클래스는 배열을 포함한 모든 클래스의 최상위 클래스다 ( 따라서 모든 클래스는 Object의 하위 클래스다)
- Objcet 클래스는 java.lang 패키지에 있다
- Object 클래스에는 배열을 포함한 모든 객체가 꼭 포함해야할 메소드가 정의되어 있다
- 배열객체를 포함한 모든 객체는 Object객체를 내부에 포함하고 있고, Object가 가진 기능을 사용할 수 있다
클래스의 형변환
기본자료형타입의 변수처럼 참조형변수도 형변환이 가능하다 ( 기본자료형 타입의 형변환은 정밀도가 높은 타입으로, 사이즈가 더 큰 타입으로의 형변환은 자동 형변환된다.)
- 생성한 객체와 참조변수의 타입이 다를때 발생
- 실제 생성한 객체와 타입이 맞는 부모객체를 바라보는 것 ( 자식객체를 부모타입의 참조변수에 대입하는 것)
- 클래스의 형변환은 자기자신과 부모타입만 해당이 된다
- 자동형변환의 경우는 하위클래스타입 객체를 상위 클래스타입의 참조변수에 저장할 때만 자동으로 형변환 된다
- 하위객체를 생성할 때 함께 생성된 상위객체를 참조하고 있을 때, 형변환 연산자를 이용해서 실제 생성한 하위객체를 참조하도록 할 수 있다.(형변환 연산자가 필요하다)
// 형변환 연산자가 필요한 경우
SmartPhone p = new Iphone();
Iphone p2 = (Iphone)P;
클래스 형변환을 사용하는 이유
객체의 종류를 제한하기 위해서이다.
아래 코드를 보면 더욱 더 이해하기 쉬울 것이다.
public void testInternet(Phone p)
타입을 이렇게 Phone p라고 적을 경우
Phone 객체부터 SmartPhone 객체, Iphone 객체, Android 객체까지
다 해당되지만 Internet 메소드는 SmartPhone 객체부터 사용이 가능하다
그렇기에 아래처럼 적어야 올바르다
public void testInternet(SmartPhone p)
이런식으로 타입을 적어야 SmartPhone 하위 객체부터 들어올 수 있다
클래스 형변환 규칙
참조변수의 클래스타입과 생성된 객체의 클래스 타입이 같을 때
- Phone p = new Phone();
- Phone 객체를 생성
- 참조변수의 클래스타입과 생성된 객체의 클래스타입이 동일한 타입인지 체크 및 같은 타입임을 체크
- 객체의 주소값이 참조변수에 대입
- 참조변수는 주소값이 가르키는 객체를 참조
참조변수의 클래스타입이 생성된 객체의 상위클래스(부모클래스) 타입일 때
- Phone p = new SmartPhone();
- SmartPhone 객체를 생성
- 참조변수의 타입과 객체의 타입이 동일한 타입인지 체크 및 다른 타입임을 확인함
- 생성된 객체에서 부터 조상객체를 탐색해서 참조변수의 타입과 동일한 클래스 타입의 객체를 탐색
- 발견한 객체가 있다면 Phone 객체의 주소값이 참조변수에 대입
- 참조변수 p는 SmartPhone객체를 바라보는 것이 아닌 Phone 객체를 바라본다
참조변수의 클래스타입이 생성된 객체의 조상클래스 타입일 때
- Phone p = new Iphone();
- Iphone 객체를 생성
- 참조변수의 타입과 생성된 객체의 타입이 동일한 타입인지 체크 및 다른 타입임을 확인
- 생성된 객체에서 부터 조상객체를 탐색하여 참조변수의 타입과 동일한 클래스 타입의 객체를 탐색
- 발견한 객체가 있다면 Phone 객체의 주소값이 참조변수에 대입
- 참조변수 p는 Iphone객체를 바라보는 것이 아닌 Phone 객체를 바라본다
참조변수의 클래스타입이 생성된 객체의 상위타입이 아닐때는 오류가 발생한다
클래스 형변환 예제
public static void main(String[] args) {
// 형변환없이 해당 타입의 변수에 담기
Phone p1 = new Phone(); // 성공
SmartPhone p2 = new SmartPhone(); // 성공
Iphone p3 = new Iphone(); // 성공
// Phone타입의 변수에 객체 담기
Phone p11 = new Phone(); // 성공 자식객체를 상위타입 참조변수에 대입
Phone p12 = new SmartPhone(); // 성공 자식객체를 상위타입 참조변수에 대입
Phone p13 = new Ihone(); // 성공 자식객체를 상위타입 참조변수에 대입
// SmartPhone타입의 변수에 객체 담기
SmartPhone p21 = new Phone(); // 오류 상위타입 객체를 대입할 수 없음
SmartPhone p22 = new SmartPhone(); // 성공 참조변수 타입과 동일한 개체 타입이라서 가능
SmartPhone p23 = new Iphone(); // 성공 자식객체를 상위타입 참조변수에 대입
// Iphone타입의 변수에 객체 담기
Iphone p31 = new Phone(); // 오류
Iphone p32 = new SmartPhone(); // 오류
Iphone p33 = new Iphone(); // 성공
}
생성하려는 객체와 참조변수의 타입이 다를 경우에 클래스 형변환이 발생한다
SmartPhone p23 = new Iphone();
위 코드를 예시로 들면 p23의 참조변수는 Iphone 객체의 주소값을 가리키는 것이 아닌 SmartPhone 객체의 주소값을 가르킨다.
Phone p13 = new Iphone();
이 코드도 위 SmartPhone p23 예시처럼 Iphone 객체의 주소값을 가리키는 것이 아닌 Phone 객체의 주소값을 가르킨다
클래스 형변환된 객체에서 인스턴스 변수와 인스턴스 메소드 사용하기
참조변수 타입과 객체의 타입이 동일할 때
참조변수 타입과 객체의 타입이 다를 때
위 p1때와 달리 Iphone 인스턴스 변수와 인스턴스 메소드는 보이지 않는다
p1때와 달리 Iphone 인스턴스 변수와 인스턴스 메소드를 사용하려고 하면 빨간줄로 오류가 발생함을 알 수 있다
참조변수 타입과 객체의 타입이 다를 때 ( 2 )
p2때랑 달리 Iphone 인스턴스 변수와 인스턴스 메소드, SmartPhone 인스턴스 변수랑 인스턴스 메소드도 보이지 않는다
2때랑 같이 Iphone 인스턴스 변수와 인스턴스 메소드, SmartPhone 인스턴스 변수랑 인스턴스 메소드를 사용하려고 하면 빨간줄로 오류가 발생함을 알 수 있다
강제 클래스 형변환 하기
- 클래스 형변환 연산자를 사용하면 생성된 객체에서 지정된 클래스타입의 객체로 형변환 할 수 있다
- 생성된 객체가 상위 클래스 타입으로 형변환되어 참조되고 있으면, 형변환된 객체의 하위타입 객체의 인스턴스 변수와 인스턴스 메소드는 사용할 수 없게된다
- 따라서, 현재 참조하고 있는 객체에서 하위타입 객체의 인스턴스 변수와 인스턴스 메소드를 사용하기 위해서는 하위타입 객체를 참조할 수 있어야 한다
public static void main(String[] args) {
Phone p1 = new Iphone();
p1.tel = "010-1111-1111";
p1.call();
Iphone객체를 생성해서 Phone타입의 참조변수로 참조하고 있다
참조변수 p1은 Phone객체의 멤버변수와 멤버메소드를 사용할 수 있음
참조변수 p1은 Iphone객체의 상위타입 객체인 Phone객체를 참조
( Iphone객체 -> SmartPhone객체 -> Phone객체 -> Obect객체로 구성되어 있음)
참조변수 p1은 그 객체들 중 Phone 객체를 참조하고 있다
참조변수 p1이 참조하는 객체를 구성하고 있는 객체들 중에서 SmartPhone객체나 Iphone객체를 참조하면 web() 기능이나 appleMusic() 기능을 사용할 수 있음
// 참조변수 p1이 참조하는 객체를 구성하고 있는 객체들 중에서 SmartPhone객체를 참조하기
SmartPhone p2 = (SmartPhone) p1;
System.out.println(p2.tel);
p2.call();
p2.ip = "211.10.100.21";
p2.email = "hong@gmail.com";
p2.web();
p2.mail();
참조변수 p2는 참조변수 p1이 참조하는 객체를 구성하고 있는 객체들 중에서 SmartPhone 객체를 탐색해서 그 객체의 주소값을 참조변수 p2에 대입한다
// 참조변수 p1이 참조하는 객체를 구성하고 있는 객체들 중에서 Iphone객체를 참조하기
Iphone p3 = (Iphone) p1;
System.out.println(p3.tel);
p3.call();
System.out.println(p3.ip);
System.out.println(p3.email);
p3.web();
p3.mail();
p3.faceId();
p3.appleMusic();
}
참조변수 p3는 참조변수 p1이 참조하는 객체를 구성하고 객체들 중에서 Iphone 객체를 탐색해서 그 객체의 주소값을 참조변수 p3에 대입한다
'Java' 카테고리의 다른 글
Java_인터페이스(oop) (1) | 2023.11.10 |
---|---|
Java_오버라이딩, 추상화, 다형성(oop) (0) | 2023.11.09 |
Java_static변수와 static메소드 (oop) (0) | 2023.11.08 |
Java_생성자, 메소드 예시(oop) (0) | 2023.11.02 |
Java_클래스와 메소드, 오버로딩(oop) (0) | 2023.11.01 |