11. 상속_김희정
상속이란?
•
부모 클래스로부터 자식클래스가 필드와 메소드 등을 물려받는 것
•
대개 부모 클래스는 추상적이고, 서브 클래스는 구체적
•
UML에서 자식 클래스 → 부모 클래스
•
상속은 is-a 관계
◦
ex) 자동차는 탈것이다. (Car is a Vehicle)
◦
ex) 대학원생, 학부생은 학생이다.
◦
has-a 관계는 상속x (ex. 도서관은 책을 가지고 있다. 직선은 양 끝점을 가지고 있다.)
상속 문법
extends 키워드
•
클래스 정의 다음에 extends 를 써주고 부모 클래스 이름을 적음.
class Car{
int speed;
public void setSpeed(int speed){
this.speed = speed;
}
}
class SportsCar extends Car{
boolean turbo;
public setTurbo(boolean newValue){
turbo = newValue;
}
}
Java
복사
상속에서의 접근 지정자 protected
•
자식 클래스는 부모 클래스의 private를 제외한 모든 멤버들을 전부 상속받음.
protected
•
protected는 자식 클래스에서만 접근 가능
•
상속 시, 다른 패키지에 있는 자식클래스에서도 접근 가능
상속을 사용하는 이유
1.
상속은 중복을 줄인다.
2.
이미 존재하는, 검증된 클래스의 필드와 메소드를 재사용할 수 있어 신뢰성 있는 SW 개발, 유지 보수 가능
super
•
부모 클래스의 메소드나 필드를 명시적으로 참조하기 위해 사용
•
메소드 재정의 시, 부모 클래스 메소드에 내용 추가하는 경우 주로 사용
class Employee {
private String name;
private int age;
private String addr;
private String team;
protected int salary;
public Employee(String name, int age, String addr, String team) {
this.name = name;
this.age = age;
this.addr = addr;
this.team = team;
}
public void printInfo(){
System.out.println("이름 : " + name);
System.out.println("나이 : " + age);
System.out.println("주소 : " + addr);
System.out.println("부서 : " + team);
}
}
class Regular extends Employee{
public Regular(String name, int age, String addr, String team) {
super(name, age, addr, team);
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public void printInfo(){
super.printInfo();
System.out.println("정규직");
System.out.println("월급 : " + salary);
}
}
Java
복사
상속과 생성자
생성자 호출 순서
부모 클래스 생성자→자식 클래스 생성자
>> 부모 클래스가 먼저 메모리에 올라가기 때문에 부모 클래스 생성자가 먼저 실행
생성자 호출 방식
1.
명시적인 호출 - super()
•
부모 클래스 생성자 호출은 반드시 생성자의 첫 줄이어야 함.
class Parent{
public Parent(){
System.out.println("부모 생성자");
}
}
class Child extends Parent{
public Child(){
super();
System.out.println("자식 생성자");
}
}
Java
복사
2.
묵시적인 호출
•
부모 클래스 생성자를 super() 같이 명시적으로 호출하지 않아도 컴파일러가 자동으로 호출해줌.
class Parent{
public Parent(){
System.out.println("부모 생성자");
}
}
class Child extends Parent{
public Child(){
System.out.println("자식 생성자");
}
}
Java
복사
파라미터에 따른 부모 클래스 생성자
•
파라미터에 따라 생성자가 선택됨.
•
오류 Case
class Shape{
public Shape(String msg){
System.out.println("shape 생성자" + msg);
}
}
class Rectangle extends Shape{
public Rectangle() {
System.out.println("Rectangle 생성자");
}
}
Java
복사
1.
Rectangle에서 부모 클래스인 Shape의 생성자 묵시적인 호출 시도
2.
자바가 자동적으로 디폴트 생성자를 추가하고 호출하려는데, 이미 Shape의 생성자가 정의되어 있기 때문에 디폴트 생성자가 자동 생성x >> 오류!
디폴트 생성자를 습관적으로 생성해야함!
12. 메소드오버라이딩
메소드 재정의(@Override)
메소드 오버라이딩은 상속된 메소드의 내용을 재정의하는 것을 말한다.
class Shape {
public void shape() {
System.out.println("도형입니다.");
}
public void draw() {
System.out.println("도형을 그립니다.");
}
}
//상속관계에서 부모의 함수을 재정의하는것(바디만 달리하는것)
class Rectangle extends Shape {
public Rectangle() {
System.out.println("사각형 생성자");
}
@Override
public void draw() {
System.out.println("사각형을 그립니다.");
}
}
class Trangle extends Shape {
public Trangle() {
System.out.println("삼각형 생성자");
}
@Override
public void draw() {
System.out.println("삼각형을 그립니다.");
}
}
public class OverrideTest {
public static void main(String[] args) {
// 1번
Shape shape = new Shape();
shape.draw();
Rectangle rc = new Rectangle();
rc.draw();
Shape shape2 = new Rectangle();
shape2.draw();
}
}
Java
복사
메소드가 재정의되었다면 부모 객체의 메소드는 숨겨지기 때문에 자식 객체에서 메소드를 호출하면 재정의된 자식 메소드가 호출된다.
메소드 오버라이딩 할 때에 주의점
•
부모의 메소드와 동일한 리턴타입,메소드 이름, 매개 변수 리스트)를 가져야한다.
•
접근 제한을 더 강하게 오버라이딩 할 수 없다.
접근 제한을 더 강하게 오버라이딩 할 수 없다는 것은 부모 메소드가 public 접근 제한을 가지고 있을 경우 오버라이딩하는 자식 메소드는 default나 private 접근 제한으로 수정할 수 없다는 뜻이다.
반대는 가능하다. 부모 메소드가 default 접근 제한을 가지면 재정의되는 자식 메소드는 default 또는 public 접근 제한을 가질 수 있다.
오버로딩(Overloading)
1.
메서드 이름이 같아야 한다.
2.
매개변수의 개수 또는 타입이 달라야 한다.
메서드의 이름이 같다 하더라도 매개변수가 다르면 서로 구별될 수 있기 때문에 오버로딩이 가능한 것이다.
위의 조건을 만족시키지 못하는 메서드는 중복 정의로 간주되어 컴파일 시에 에러가 발생한다.
그리고 오버로딩된 메서드들은 매개변수에 의해서만 구별될 수 있으므로 반환타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다는 것에 주의
(이름이 cat인 메서드가 총 3개 있지만 매개변수의 유형과 개수가 다름)
오버로딩의 가장 대표적인 예가 자주 사용하는 println메서드이다. 지금까지 println메서드의 괄호 안에 값만 지정해주면 화면에 출력하는데 아무런 어려움이 없었다. 하지만, 실제로는 println메서드를 호출할 때 매개변수로 지정하는 값의 타입에 따라서 호출되는 println메서드가 달라진다.
PrintStream클래스에서는 어떤 종류의 매개변수를 지정해도 출력할 수 있도록 아래와 같이 10개의 오버로딩 된 println 메서드를정의해놓고 있다.
void println();
void println(boolean x);
void println(char x);
void println(char[] x);
void println(double x);
void println(float x);
void println(int x);
void println(long x);
void println(object x);
void println(String x);
Java
복사
println메서드를 호출할 때 매개변수로 넘겨주는 값의 타입에 따라서 위의 오버로딩된 메서드들 중의 하나가 선택되어 실행되는 것이다.
13. 다형성
객체 지향의 원리: 다형성 (Polymorphism)
1. 개념
“하나의 부모 타입”의 참조 변수가 “여러 개의 자식 타입”의 인스턴스(객체)를 가질 수 있는 성질을 의미한다.
프로그램 언어의 다형성은 그 프로그래밍 언어의 자료형 체계의 성질을 나타내는 것으로, 프로그램 언어의 각 요소들(상수, 변수, 식, 오브젝트, 함수, 메소드 등)이 다양한 자료형(type)에 속하는 것이 허가되는 성질을 가리킨다. [위키백과]
2. 구현방식
자바 문법에서 다형성은 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조하는 방식으로 구현된다. 이것을 업캐스팅(upcasting, 상형 형변환)이라고 한다.
Shape s1 = new Shape();
Shape s2 = new Circle();
Java
복사
3. 필수 조건
•
상속 관계
◦
부모-자식 클래스 간 상속 관계가 이루어져야 한다.
•
메소드 오버라이딩
◦
하위 클래스 내 메소드 함수가 재정의되어야 한다.
•
업캐스팅
◦
부모 클래스 타입으로 자식 클래스 객체를 생성하여 형변환하여야 한다.
4. PPT 예제
class MobilePhone {
protected String number;
public MobilePhone(String num) {
number = num;
}
public void answer(){
System.out.println("Hi~from " + number);
}
}
class SmartPhone extends MobilePhone{
private String androidVer;
public SmartPhone(String num, String ver) {
super(num);
androidVer = ver;
}
public void playApp() {
System.out.println("App is running in " + androidVer);
}
}
public class Phone {
public static void main(String[] args) {
SmartPhone ph1 = new SmartPhone("010-555-7777", "Nougat");
MobilePhone ph2 = new SmartPhone("010-999-3333", "Nougat");
ph1.answer(); //Hi~from 010-555-7777
ph1.playApp(); //App is running in Nougat
System.out.println();
ph2.answer(); //Hi~from 010-999-3333
ph2.playApp(); //컴파일 에러
}
}
Java
복사
5. 다형성의 장점
•
코드 작성 시 다형성을 고려하여 작성하면 유연하고 확장성 있으며 유지보수가 간편해진다.
◦
다형성을 적용하는 것이 코드 설계의 효율성을 가져온다.
•
부모 클래스 타입으로 선언할 경우, 훨씬 넓은 범위의 객체를 받을 수 있고 자식 클래스 객체를 일일히 생성해야 하는 수고를 덜어준다.
+ instanceof 연산자
//문법
객체 instanceof 타입
//사용 예
if (ph1 instanceof SmartPhone) {
System.out.println("TRUE");
} else {
System.out.println("FALSE");
} // "TRUE" 출력
if (ph2 instanceof SmartPhone) {
System.out.println("TRUE");
} else {
System.out.println("FALSE");
} // "TRUE" 출력
if (ph2 instanceof MobilePhone) {
System.out.println("TRUE");
} else {
System.out.println("FALSE");
} // "TRUE" 출력
Java
복사
•
참조 변수가 실제 참조하고 있는 인스턴스 객체의 타입을 확인할 수 있다.