신용권님의 ''이것이 자바다'' 공부 기록
책을 보면서 내용을 정리했습니다. 이것이 자바다 커뮤니티 : https://cafe.naver.com/thisisjava
현실 세계에서 부모가 자식에게 물려주는 행위를 말한다. 현실 세계에서는 부모가 자식을 선택한다. 객체 지향 프로그램에서 상속이란 자식(하위, 파생) 클래스가 부모(상위) 클래스의 멤버를 물려받는 것을 말한다. 현실 세계와는 다르게 자식이 부모를 선택해서 물려받을 수 있으며, 부모의 필드와 메소드가 상속대상이다.
자식 클래스가 상속할 부모 클래스를 지정하는 키워드
자바는 단일 상속으로 다수의 부모 클래스를 나열할 수 없다.
class ChildClass extends SuperClass1, SuperClass2 {...} // 불가
class ChildClass extends SuperClass1 {...} // 단일상속
부모 객체를 생성할 때, 부모 생성자를 선택하여 호출할 수 있다.
ChildClass(parameter, ...) {
super(parameter, ...);
...
}
super(매개값, ...): 매개값과 동일한 타입, 개수, 순서가 맞는 부모 생성자를 호출한다.
부모 생성자가 없다면 컴파일 오류가 발생한다.
super()은 반드시 자식 생성자의 첫 줄에 위치하여야한다.
부모 클래스에 기본(매개변수 없는) 생성자가 없다면 필수로 작성하여야 한다.
부모 클래스의 상속 메소드를 수정하여 자식 클래스에서 재정의하는 것을 말한다. 재정의 조건으로는 부모 클래스의 메소드와 동일한 시그니쳐를 가져야하며 접근 제한자를 더 강하게는 재정의가 불가하다.
public final class ClassName {...}
상속과 관련된 접근 제한자로 같은 패키지내에선 default 접근제한자와 동일하고, 다른 패키지에서는 자식 클래스만 접근을 허용한다.
같은 타입이지만 실행 결과가 다양한 객체 대입(이용) 가능한 성질을 다형성이라한다. 부모 타입에는 모든 자식 객체가 대입 가능하다. (자식 타입은 부모 타입으로 자동 타입 변환) 다형성을 활용하면 객체 부품화가 가능하다.
자식클래스 변수 = (자식클래스) 부모클래스타입; //강제 타입 변환
부모 타입이면 모두 자식 타입으로 강제 타입 변환할 수 있는 것은 아니다.
ClassCastException 예외가 발생할 수 있다.
Parent parent = new Parent();
Child child = (Child)parent; //강제 타입 변환을 할 수 없다.
먼저 자식 타입인지 확인 후 강제 타입을 실행하여야 한다.
boolean result = (객체) instanceof (타입)
public void method(Parent parent) {
if(parent instanceof Child) {
Child child = (Child) parent;
}
}
package com.kosta.day07;
//Account 다형성연습
public class AccountTest2 {
public static void main(String[] args) {
//계좌 4개 만들기: 배열사용
//Account
//CreditLineAccount
//BonusAccount
//CheckingAccount
Account[] accounts = new Account[4];
makeAccount(accounts);
printAccount(accounts);
System.out.println("---------Casting Account");
castingAccount(accounts);
}
private static void castingAccount(Account[] accounts) {
for(Account arr:accounts) {
if(arr instanceof CreditLineAccount) {
System.out.println("=========Casting CreditLineAccount");
//new CreditLineAccount() -> Account -> CreditLineAccount
CreditLineAccount creditLineAccount = (CreditLineAccount) arr;
System.out.println("마이너스한도: " + creditLineAccount.getCreditLine());
}else if(arr instanceof BonusAccount) {
System.out.println("=========Casting BonusAccount");
//new BonusAccount() -> Account -> BonusAccount
arr.deposit(1000);
BonusAccount bonusAccount = (BonusAccount) arr;
bonusAccount.deposit(2000);
System.out.println(bonusAccount.bonusPoint + " 포인트");
}else if(arr instanceof CheckingAccount) {
System.out.println("=========Casting CheckingAccount");
//new CheckingAccount() -> Account -> CheckingAccount
CheckingAccount checkingAccount = (CheckingAccount)arr;
System.out.println("카드번호: " + checkingAccount.getCardNo());
int amount = checkingAccount.pay("0212", 100);
System.out.println(amount);
}
}
}
private static void printAccount(Account[] accounts) {
for(Account arr:accounts) {
System.out.println(arr);
System.out.println("==========================================");
}
}
private static void makeAccount(Account[] accounts) {
//자동형변환: 부모타입 = 자식객체
accounts[0] = new Account("111", "kim", 100);
accounts[1] = new CreditLineAccount("222", "lim", 100, 500);
accounts[2] = new BonusAccount("333", "bae", 100, 10);
accounts[3] = new CheckingAccount("444", "park", 100, "0212");
}
}
추상(abstract)란 실체들 간에 공통되는 특성을 추출한 것을 말한다. 예로 새, 곤충, 물고기를 보고 동물이란 것을 추상하듯이 이러한 특성을 추출하는 것을 추상이라 한다. 추상 클래스(abstract class)는 실체 클래스들의 공통되는 필드와 메소드를 정의한 클래스를 말한다. 추상 클래스는 실체 클래스의 부모 클래스 역할을 한다. 그렇다고 단독 객체는 아니다.
New 연산자로 객체를 생성하지 못하고 상속을 통해 자식 클래스만 생성할 수 있다.
클래스 선언시 abstract 키워드를 사용한다
public abstract class ClassName {
//field
//constructor
//method
}
메소드 이름은 동일하지만, 실행 내용이 실체 클래스마다 다른 메소드를 재정의된 메소드라 말한다.
구현 방법
//추상 클래스
public abstract class Animal {
public abstract void sound();
}
//실체 클래스
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("bow bow");
}
}
//실체 클래스
public class Cat extends Animal {
@Override
public void sound() {
System.out.println("meow meow");
}
}
출력 결과 >>
Shape 0 is a BLUE Circle with an area of 314.15927, a radius of 10.0, and a perimeter of 62.831854
Shape 1 is a RED Rectangle with an area of 35.0 and a perimeter of 24.0
Shape 2 is a GREEN Circle with an area of 201.0619328, a radius of 8.0, and a perimeter of 50.2654832
package com.kosta.day07;
/*
abstract class: abstract method가 하나이상 존재한다.
abstract method: 함수의 정의는 있으나 구현은 없다. > 구현은 해당 class를 상속받은 자식클래스에서 반드시 한다.
*/
public abstract class Shape {
private String color;
private String type;
public Shape(String color, String type) {
this.color = color;
this.type = type;
}
//--------------------------------규격--------------------------------
//calculateArea: 면적구하기
public abstract double calculateArea(); //정의는 있고 구현은 없음 (추상 메소드)
//어떤도형인지 결정되지않아 면적구하기 불가
//calculatePerimeter(): 둘레구하기
public abstract double calculatePerimeter(); //정의는 있고 구현은 없음 (추상 메소드)
//어떤도형인지 결정되지않아 둘레구하기 불가
//-------------------------------------------------------------------
public String getColor() {
return color;
}
public String getType() {
return type;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(color).append(' ');
sb.append(type);
return sb.toString();
}
}
package com.kosta.day07;
public class Circle extends Shape{
int radius;
double circumference;
Circle(String color, int radius) {
super(color, "Circle");
this.radius = radius;
}
double getRadius() {
return radius;
}
@Override
public double calculateArea() {
return radius*radius*Math.PI;
}
@Override
public double calculatePerimeter() {
circumference = 2*radius*Math.PI;
return circumference;
}
}
package com.kosta.day07;
public class Rectangle extends Shape{
int width;
int height;
public Rectangle(String color, int width, int height) {
super(color, "Rectangle");
this.width = width;
this.width = height;
}
@Override
public double calculateArea() {
return width * height;
}
@Override
public double calculatePerimeter() {
return 2 * (width + height);
}
}
package com.kosta.day07;
public class TestShape {
public static void main(String args[]) {
Shape[] s = new Shape[3];
s[0] = new Circle("BLUE", 10);
s[1] = new Rectangle("RED", 5, 7);
s[2] = new Circle("GREEN", 8);
for (int i = 0; i < 3; i++) {
if (s[i] instanceof Circle) {
System.out.println("Shape " + i + " is a " + s[i]
+ " with an area of " + s[i].calculateArea()
+ ", a radius of " + ((Circle) s[i]).getRadius()
+ ", and a perimeter of " + s[i].calculatePerimeter());
} else if (s[i] instanceof Rectangle) {
System.out.println("Shape " + i + " is a " + s[i]
+ " with an area of " + s[i].calculateArea()
+ " and a perimeter of " + s[i].calculatePerimeter());
}
}
}
}