상속(inheritance)
상속을 통해 유지 보수가 쉽고, 중복을 방지하며, 프로그램의 수정 및 추가가 유연한 프로그램을 만들 수 있다.
•
사전적으로 상속은 친족 관계에서 한 사람이 다른 사람에게 재산에 관한 권리와 의무의 일체를 이어주고, 이어받는 것이다.
•
실생활에서는 부모님이 자식들에게 재산을 상속한다.
•
프로그램에서는 클래스 간에 상속이 일어난다. B 클래스가 A 클래스를 상속받으면 B 클래스는 A 클래스의 필드와 메서드를 사용할 수 있다.
클래스의 상속
•
상속을 간단히 그려보면 위와 같다.
•
상속하는 클래스는 “부모 클래스” 혹은 “상위 클래스”라고 부른다. 상속받는 클래스는 “자식 클래스” 혹은 “하위 클래스”라고 부른다.
•
클래스의 관계는
동물 클래스(부모) → 사자 클래스(자식), 개 클래스(자식), 고양이 클래스(자식)
와 같이 부모 클래스는 추상적이고 자식 클래스는 구체적이어야 한다.
•
자바에서 상속을 할 때는 예약어 “extends”를 활용한다.
•
상속을 받는 자식 클래스 뒤에 extends 를 사용하고 부모 클래스를 적어주면 된다. 예를 들어, 클래스 A를 클래스 B가 상속받을 때 그 코드는 다음과 같다.
class (자식) 클래스명 extends (부모)클래스명 { ... }
class A {
...
}
class B extends A {
...
}
Java
복사
클래스 상속의 예제
클래스 상속의 활용과 이점을 예제를 통해 알아보자.
•
Car, Truck, Bus 클래스를 만들어, 다음 출력문을 출력하는 프로그램을 만든다고 가정하자.
◦
클래스에는 speed를 설정하는 setSpeed(), String을 반환하는 drive() 메소드가 포함되어야 한다.
(Console)
시속 100Km로 승용차를 운전합니다.
시속 80Km로 화물차를 운전합니다.
시속 60Km로 버스를 운전합니다.
상속을 사용하지 않을 때
•
Car, Truck, Bus 클래스를 각각 만든다면, 클래스마다 speed, type 등을 선언해야 하고 setSpeed(), drive() 메소드 등을 적어야 한다.
•
이러한 방법을 사용하면 클래스마다 중복되는 코드가 생기며, 기능을 추가하고 싶을 때 역시 각 클래스마다 기능을 추가해야 하므로 번거롭다.
예제코드
상속을 사용할 때
•
Vehicle이라는 부모 클래스를 만들어 변수와 메소드를 한번만 작성하고, Car, Truck, Bus 클래스에서 Vehicle의 필드와 메소드를 활용할 수 있다.
예제코드
상속을 사용하는 이유
상속은 다양한 장점을 갖는다.
•
중복되는 코드를 줄일 수 있다.
•
부모 클래스의 코드를 재사용할 수 있다.
•
이미 검증된 소프트웨어를 재사용할 때 유용하며, 그러한 소프트웨어를 손쉽게 개발, 유지 및 보수하기에 유리하다.
•
부모 클래스의 필드와 메소드를 자식 클래스에서 활용할 때 접근 제어자와 예약어 super를 적절히 활용할 수 있다.
상속과 생성자
•
자식 객체를 위해, 부모 클래스의 생성자 호출이 먼저 완료되어야 한다.
•
생성자 호출 순서
◦
부모 클래스의 생성자 → 자식 클래스의 생성자
•
즉, 자식 객체를 호출하면 자동으로 부모 생성자가 먼저 호출이 됨.
•
자식 생성자로 super(); 를 사용
명시적인 생성자 호출
public class Parent{
public Parent() {
System.out.println("부모 생성자");
}
}
public class Child extends Parent{
public Parent(){
super(); //명시적으로 생성자를 코딩함
System.out.println("부모 생성자");
}
}
Java
복사
묵시적인 생성자 호출
1.
class A {
2.
// 디폴트 생성자: 파라미터가 없는 생성자
3.
public A() {
4.
// 생성자 구현부 생략..
5.
}
6.
}
public class Parent{
public Parent() {
System.out.println("부모 생성자");
}
}
public class Child extends Parent{
public Parent(){
// super(); 묵시적으로 생성자를 코딩함, 컴팡일러가 자동으로 호출
System.out.println("부모 생성자");
}
}
Java
복사
•
오류 발생 경우
◦
기본 생성자가 없는데 사용할 경우.
오버로딩 (Overloading)
메서드 오버로딩 (Method Overloading)
→ 매개변수의 수나 타입은 다르고, 이름은 같게 다른 메서드를 정의하는 것
class Calculator {
// case 1
int sum(int x, int y){
return x + y;
}
// case 2
double sum(double x, double, y){
return x + y;
}
// case 3 → error
int sum(int x, double y){
return x + (int)y;
}
// case 4 → error
double sum(int x, double y){
return x + y;
}
}
Java
복사
오버로딩의 조건
•
메서드의 이름이 같아야 한다.
◦
case1, case2, case3, case4 모두 이름이 같다.
•
메서드의 매개변수 수나 타입이 달라야 한다.
•
메서드의 매개변수 수와 타입이 같고 리턴값이 다른 경우, 오버로딩이 성립하지 않는다.
◦
case3와 case4는 오버로딩이 성립되지 않는다.
오버라이딩
메소드 오버라이딩
자식클래스가 부모클래스의 메소드를 자신의 필요에 맞추어 재정의한다.
단, 함수 바디만 달리 하여야한다.
class Shape{ public void draw() { System.out.println("Shape"); } }
class Circle extends Shape {
@Override
public void draw() { System.out.println("Circle을 그립니다."); }
}
class Rectangle extends Shape {
@Override
public void draw() { System.out.println("Rectangle을 그립니다."); }
}
class Triangle extends Shape {
@Override
public void draw() { System.out.println("Triangle을 그립니다."); }
}
Java
복사
Shape 클래스를 부모로 가지는 Circle, Rectangle, Triangle 클래스들은 Shape의 draw 메소드를 활용가능하지만, 위의 표기처럼 같은 이름, 같은 매개변수와 결과 값을 가진 새로운 메소드로 재정의 가능하며 자식을 객체로 불러왔을 때, 오버라이딩된 자식의 메소드로 사용된다.
다형성
장진선 정상희
다형성이란?
•
하나의 객체가 여러 가지 타입을 가질 수 있는 것.
•
상위 크래스가 동일한 메시지로 하위 클래스들을 서로 다르게 동작 시키는 객체 지향 원리이다.
•
다음 예시를 보자
class Shape{
public void draw() {
System.out.println("도형을 그립니다.");
}
}
class Rectangle extends Shape{
@Override
public void draw() {
System.out.println("사각형을 그립니다.");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("삼각형을 그립니다.");
}
}
public class ShapeTest {
public static void main(String[] args) {
// 1번
Shape shape = new Shape();
shape.draw();
// 2번
Rectangle rectangle = new Rectangle();
rectangle.draw();
// 3번
Triangle triangle = new Triangle();
triangle.draw();
}
}
Java
복사
이와 같이 상속 관계인 상위 클래스의 함수, 변수를 덮어쓰는 것이 다형성이다.
상위클래스의 함수를 하위 클래스에서 메소드 오버라이딩을 하며, 여러 가지 결과를 만들어낼 수 있다.
다형성의 장점
1.
유지보수가 쉽다.
•
여러 객체를 하나의 타입으로 관리가 가능하기 때문에 코드 관리가 편리해 유지보수가 용이하다.
2.
재사용성이 증가 한다.
•
객체를 재사용하기 쉬워지기 때문에 개발자의 코드 재사용성이 높아진다.
3.
안정성이 높아진다.
•
클래스간의 의존성이 줄어들어 결합도가 낮아지며 확장성이 높아져 안정성이 높아집니다.
다형성의 필수 조건
1.
상속관계
•
다형성을 활용하기 위해서는 부모-자식 간 클래스 상속이 필수로 이루어져야 한다.
2.
오버라이딩 - 메소드 재정의
•
다형성이 보장되기 위해서는 하위 클래스 메소드가 반드시 재정의 되어 있어야 한다.
3.
업캐스팅 (UpCasting) - 부모클래스의 타입으로 형변환
•
부모 타입으로 자식클래스를 업캐스팅하여 객체를 생성해야 한다.
캐스팅 : 형변환을 의미
•
업캐스팅 (UpCasting) : 자손타입의 참조변수를 조상타입의 참조변수로 변환하는 것
•
다운캐스팅 (DownCasting) : 조상타입의 참조변수를 자손타입의 참조변수로 변환하는 것
다형성 구현 방법
1. 상속 클래스 구현
2. 메소드 오버라이딩
3. 업캐스팅하여 객체 선언
4. 부모 클래스 객체로 자식 메소드 호출