객체지향의 4가지 주요 특성
OOP is APIE
Oject Oriented Programming is Abstraction, Polymorphism, Inheritance, Encapsulation
추상화 다형성 상속 캡슐화
그 중에서도 다형성에 대해... 수업시간에 이해가 잘 안돼서 다시 정리해봤다.
(이하 같은 .java파일에 있으나 여러 코드블럭으로 쪼개봄)
class Creature {
int age;
Creature() {
System.out.println("- Creature created.");
}
void breathe() {
System.out.println("- breathing.");
}
}
Creature 클래스
- 멤버변수 age
- 생성자 Creature()
- 메서드 breathe()
class Person extends Creature {
String name;
Person() {
System.out.println("- Person created.");
}
void walk() {
System.out.println("- walking.");
}
void eat() {
System.out.println("- eating.");
}
}
Person 클래스 (Creature를 상속받음)
- 멤버변수 name
- 생성자 Person()
- 메서드 walk()
- 메서드 eat() - (eating)
class Student extends Person {
int grade;
Student() {
System.out.println("- Student created");
}
Student(int grade) {
this.grade = grade;
}
void eat() {
System.out.println("- drinking.");
}
}
Student 클래스
- 멤버변수 grade
- 생성자 Student()
- (오버로딩한) 생성자 Student(int grade)
- (Person의 것을 오버라이딩한) 메서드 eat() - (drinking(
public class ClassTest_Polymorphism {
public static void main(String[] args) {
//
System.out.println("<1>");
Person p1 = new Person();
p1.walk(); // 당연한 객체의 메서드 호출.
// 다형성에 대해...
System.out.println("<2>");
Creature c1 = new Student(); // Creature 객체를 생성하는데 자식의 자식 클래스인 Student를 참조.
c1.breathe(); // 메모리 자체는 단순 Creature가 아닌 Person에 Student까지도 만들어지지만, 접근 가능 범위는 Creature까지만 가능.
Student s1 = (Student) c1; // 그 객체를 Student로 명시적 캐스팅하면 접근도 가능해짐.
s1.eat(); // Student가 Person의 것을 오버라이딩한 eat함수가 호출됨.
System.out.println("<3>");
Creature c2 = new Creature(); // 그러면 Student 클래스를 참조하지 않은 Creature 객체를 생성하면?
// Student s2 = (Student) c2; // 명시적으로 캐스팅할 수도 없음.
// s2.eat(); // 그니까 이것도 할 수가 없음.
System.out.println("<4>");
Person p2 = new Student(); // Person 클래스의 객체를 생성할 때 자식인 Student 클래스를 참조하면 메모리상으로 Student가 생성되나 접근은 할 수 없음.
p2.eat(); // 하지만 Person인 p3의 eat()함수를 호출하면 메모리상에 있는 오버라이딩된 자식클래스의 eat()가 호출됨.
}
}
main문이 있는 다형성테스트클래스
주석이 있지만 보충하자면
<1> - p1객체를 Person 타입으로 아주 일반적으로 생성함. 그리고 Person 클래스의 멤버 메서드인 walk를 당연하게 호출함.
<2> - Creature 타입으로 c1객체를 생성하는데, 자식의 자식 클래스인 Student를 참조함. (먼저 Creature가 있고, Person이 그걸 상속받고, Student가 그걸 상속받은 구조라는 걸 기억) 메모리상에는 Student까지 생성이 됐으나, 접근은 Creature까지 밖에 접근이 안됨. 즉 생성은 크게 됐지만 좁게만 접근 가능한 상태. 하지만 이걸 Student 타입으로 명시적 캐스팅을 해주면서 Student 타입의 s1에 넣어주면? 접근도 가능해지면서, eat()함수를 호출할 수 있게 됨. (근데 이 eat()함수는 Student의 것인데 Person의 것을 오버라이딩한 것임.)
<3> - Creature 타입으로 c2객체를 그냥 생성함. 근데 이걸 Student타입으로 명시적 형변환을 할 수는 없음. "조상을 무작정 자손으로 바꿀 수는 없다."라고 강의안에 나와있음. 그러니까 당연히 자식 클래스의 메서드를 쓸 수도 없음.
<4> - Person 타입으로 p2객체를 생성하는데 자식인 Student 클래스를 참조함. 그러면 메모리상에서는 Student가 생성은 되지만 Person만 접근이 가능한 상태. 하지만 eat()를 호출하면 자식클래스인 Student에서 오버라이딩한 eat()가 실행됨.
출력:
<1>
- Creature created.
- Person created.
- walking.
<2>
- Creature created.
- Person created.
- Student created
- breathing.
- drinking.
<3>
- Creature created.
<4>
- Creature created.
- Person created.
- Student created
- drinking.
일단 내가 이해가 안됐던 부분들은 이렇게 만들어봄으로 대충 이해가 된 것 같다.
'코딩 > Java' 카테고리의 다른 글
Java - Static에 대하여... (0) | 2023.06.11 |
---|---|
Java - Interface에 Abstract가 아닌 메서드를 작성할 수 있다?? (0) | 2022.02.05 |
Java Singleton Pattern(싱글톤 패턴) (0) | 2022.01.26 |
java - 왜 인터페이스? (0) | 2022.01.26 |
java - 기본 자료형 정리 (0) | 2022.01.19 |