[게임개발기] 01. 게임 정체성 및 시나리오 정하기
상속(Inheritance)
상속의 개념
[ 상속이란 ]
상속이란, 기존에 정의된 클래스(부모 클래스, 상위 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스, 하위 클래스)가 물려받아 재사용할 수 있도록 하는 개념
[ 상속을 사용하는 이유 ]
• 소프트웨어를 재사용(reuse)하는 방법
• general class definition -> specialized class를 간단하고 효과적으로 정의
• 기존내용을 변경해 클래스를 정의하여 필요한 정보만 추가
상속과 객체 간 관계
[ Inter-class Relationships ]
IsA relation(상속 관계)
• 하위 타입(subtype)을 정의함
• 주로 공통적인 속성과 기능을 재사용하고자 할 때 사용
• A(자식클래스)가 B(부모클래스)의 일종이다 라는 의미
• Java에서 extends 키워드를 사용함
// 자동차는 탈것(Vehicle)의 일종이다
class Automobile extends Vehicle { ... }
// 상속관계(isA)를 예로 설명한 도형 클래스 계층도
Shape
/ \
2DShape 3DShape
/ | \ | \
Oval Rectangle Triangle Sphere Cube
| | |
Circle Square EquilateralTriangle
\
IsoscelesTriangle
Parallelogram
|
Diamond
HasA relation(포함 관계)
• 복합 객체(composite)를 정의함
• 객체를 하위 구성요소로 포함함
• 코드에서는 클래스 내부에 다른 객체 타입을 필드로 선언함으로써 표현
• 이런 관계는 클래스 내부에 부품처럼 다른 객체를 조립해서 쓰는 구조
• A가 B를 갖고 있다는 의미
// 자동차는 바퀴를 갖고 있다" → 자동차 클래스 안에 Wheel 객체를 포함
class Automobile ... {
Color shade;
Wheel wheels[4];
...
}
[ Object 클래스와 메서드들]
정의
Object클래스
클래스 계층 구조의 최상위 클래스로, 모든 클래스는 Object의 메소드를 자동으로 상속
클래스 계층의 뿌리 (※객체가 아닌Object라는 이름)
java.lang 패키지에 정의되어 있음
모든 클래스의 슈퍼클래스 (기본 명세 제공)
clone()
equals(Object) // 두 객체가 같은지 비교
finalize()
getClass()
hashCode() // 객체의 해시값 반환 (HashMap, HashSet에 중요)
notify() // 멀티스레드 간의 대기/알림 기능
notifyAll()
toString() // 객체를 출력할 때 문자열로 표현
wait([long][, nanosec]) // 멀티스레드 간의 대기/알림 기능
참고
java SE document를 구글에 검색해서 → Oracle의 공식 Java API 문서에 들어감
java.base 모듈 → java.lang 패키지 → Object 클래스를 확인
클래스 계층과 함께 Object 클래스의 메소드 요약(설명 포함)을 볼 수 있음
[ 요약 ]
• 상위 클래스의 변수/메소드를 상속-> 재활용 한다
(e.g., student: getName() == super.getName())
• 모든 (학생/교수/직원)을 한 가지의 종류(Person)으로 다
룰/저장할 수 있다: 다형성(polymorphism)
• 상위 클래스의 생성자를 호출/실행할 수 있다
(e.g., super(…));
• 상위 클래스의 메쏘드를 overriding 하기도 한다
(e.g., student: info() == Student.info() =! Person.info())
• 상위 클래스의 overridden 메쏘드를 직접 호출할 수 있다(e.g., super.info())
메소드 오버라이딩
overriding, 대체
[ 정의 ]
클래스 상속 관계에서 반환자료형, 메쏘드 이름, 인자형과 인자수가 같을 때 파생 클래스의 메쏘드를 사용하는 것
[ 오버로딩 vs 오버라이딩 ]
overriding(대체) <-> overloading(중복, 한 클래스 내에서)
[ 오버라이딩의 내부 실행 과정 ]
student.getName()
메쏘드 호출 > 현클래스에서 메쏘드 탐색 > 없으면 직상위 클래스 탐색 > 없으면 차상위 > 결국 못찾으면 오류(compile error)
[ 예시 ]
People - Student - MaleStudent hierarchy:
• People → writeOutput() 출력: “a”
• Student2 → writeOutput() 출력: “b”
• MaleStudent → writeOutput() 출력: “c”
참고 오버라이딩된 메서드는 가장 하위 클래스의 것을 우선 실행함
People → Student2 → MaleStudent
| 클래스 | 멤버변수 | 접근제어자 | 자식클래스 접근 |
|---|---|---|---|
| People | penName | private | ❌ |
| People | name | protected | ⭕ |
| Student2 | studentYear | private | ❌ |
| MaleStudent | doArmy | private | ⭕ |
class People {
private String penName;
People() { ... }
People(String name) { ... }
public String changeName(String name) {
this.name = name;
}
public void writeOutput() {
System.out.println("내 이름: " + name);
}
protected String name;
}
// name은 protected로 선언되어, 하위 클래스(Student2, MaleStudent)에서 사용 가능
// penName은 private이라 자식 클래스에서 접근 불가
class Student2 extends People {
Student2() { ... }
Student2(String name, ...) { ... }
public void reset(String name, int year) {
changeName(name);
studentYear = year;
}
public void writeOutput() {
System.out.println("제 이름: " + name);
}
private int studentYear;
}
// changeName()을 호출해 People 클래스의 name 필드를 설정
// studentYear는 private이므로 MaleStudent에서 직접 접근 불가
class MaleStudent extends Student2 {
MaleStudent() { ... }
MaleStudent(String name, ...) { ... }
public void writeOutput() {
System.out.println("제 이름: " + name);
System.out.println("학년: " + studentYear);
System.out.println("병역필: " + doArmy);
}
private boolean doArmy; // dutyOfArmy
}
// name은 protected → 접근 가능
// studentYear는 private → 직접 접근 불가 (오류 발생)
// doArmy는 자신의 클래스에 선언된 private → 내부에서는 접근 가능
다형성 (feat. overriding)
다형성이란
[ 클래스 상속에 의한 계층구조에서 method의 다형성 ]
• 어떤 A라는 객체가 동작하는데 같은 상황임에도 불구하고 다른 모습을 갖거나, 다른 동작을 하는 (것처럼 보이는) 현상
• 상속 관계에서 overriding으로 나타나는 현상/특성
[ 예시 - animal farm choir ]
class Animal {
private int nLegs = 4;
public void talk() {
System.out.println(“조용~“);
}
}
class Dog extends Animal {
public void talk() { System.out.println(“멍멍!“); }
}
class Pig extends Animal {
public void talk() { System.out.println(“꿀꿀!“); }
}
class Snake extends Animal {
private int legs = 0;
}
public class AnimalFarmChorus{
public static void main(Stirng[] args){
Dog aDog = new Dog();
Pig aPig = new Pig();
Animal animal;
// polymorphism
// 같아 보이는 animal 인데 talk()를 자동 선택해줌
animal = aDog; // promotion: dog > animal
animal.talk();
animal = aPig;
animal.talk();
// without polymorphism
if(animal == aDog) aDog.talk();
else if(animal == aPig) aPig.talk();
}
}
// result: 멍멍 > 꿀꿀
다형성을 만드는 두가지 방법!
[ 메서드 오버로딩 (Method Overloading) ]
• 같은 이름의 메서드/생성자를 매개변수만 다르게 정의하는 것(반환형만 다르면 안됨)
• 컴파일 시점(polymorphism at compile time)에 어떤 메서드가 호출될지 결정됨
[ 메서드 오버라이딩 (Method Overriding) ]
• 상속받은 메서드를 하위 클래스에서 재정의하여 다른 동작을 하게 함
• 실행 시점(polymorphism at runtime)에 어떤 메서드가 호출될지 결정됨
|구분|오버로딩|오버라이딩|
|—|—|—|
|다형성 종류|컴파일 타입 다형성|런타임 다형성|
|대상|같은 클래스, 상속 관계|상속 관계에서만|
|조건|이름은 같고, 매개변수가 다름|이름, 매개변수, 반환형 모두 동일|
|결정시점|컴파일|실행|
|@Overrid 필요|필요없음|권장|
다형성의 실현
상속관계에서 메쏘드 overriding으로 다형성 실현
• 하나의 이름/(인터페이스)에 서로 다른 구현
• 수퍼 클래스의 메쏘드 draw(), talk()를 여러 서브 클래스에서 각각 목적에 맞게/다르게 (재)구현
• Shape의 draw() 메소드를 Line, Rect, Circle에서‘대체’하여 다르게 구현
// super class - Shape
class Shape{
public void draW(){
System.out.println("Shape");
}
}
// super class - Line
class Line extends Shape{
public void draW(){
System.out.println("Line");
}
}
// super class - Rect
class Rect{
public void draW(){
System.out.println("Rect");
}
}
// super class - Circle
class Circle{
public void draW(){
System.out.println("Circle");
}
}
캐스팅과 기타 문법(static, fianl)
[ Casting ]
| 종류 | 내용 |
|---|---|
| Promotion (승급) | • subclass 객체를 superclass 객체로 치환 • Animal animal = aDog; |
| Demotion (강등) | • superclass 객체를 subclass 객체로 치환 • casting: 강제적 형변환이 필요하다 Dog bDog = (Dog) animal;• 컴파일러 타당/통과: animal이 위처럼 원래 Dog 객체가 아니었다면 실행할 때 오류가 발생 |
[ instanceof 연산자 ]
💡
instanceof연산자
참조(변수)가 가리키는 객체의 유형(class) 식별
• 형식:객체_참조 instanceof 클래스명
• 연산의 결과:true,false
Person p = new Professor();
// new Professor() 객체는 Professor 타입이면서, 동시에 Employee 타입이기도 하고, Person 타입이기도 함
If (p instanceof Person) //true
If (p instanceof Student) // false. Student를 상속받지 않았다
If (p instanceof Employee) // true
If (p instanceof Professor) // true
If ("java" instanceof String) // true
If (3 instanceof int) // 문법 오류. instanceof는 참조 자료형에만 사용
[ final and static ]
final
├─ 변수 → 값 고정 (변경 ❌)
├─ 메서드 → 자식 클래스에서 오버라이딩 ❌
└─ 클래스 → 다른 클래스가 상속 ❌
//클래스에 final이 붙으면 상속자체가 X > 오버라이딩 X
static final
오버라이드(재정의) 불가능한 클래스 변수
• static final로 선언된 변수는 변경할 수 없는 상수
• 클래스 차원에서 고정된 값
static final float CmPerInch = 2.54;
본질적으로 상수인 변수들 (constant)
• final static 조합은 상수 선언에 자주 사용
• 공용(static)이고, 변경 불가능(final)함
public final static float C = 2.9989E+10f;
public final static int SCREEN_WIDTH = 640;
주의 오버라이드 금지 예시
class A {
final int a;
}
class B extends A {
float a; // ❌ 오류! final 변수는 하위 클래스에서 재정의 불가
}
final class Dinosaur { ... }
void with(final Animal a) {
// a = new Animal(); ← ❌ final 파라미터는 값 변경 불가
a.talk(); // ✅ 사용은 가능
}
// final class: 상속 금지
// final parameter: 메서드 매개변수 값 변경 불가