소개
이 랩에서는 Java 객체 지향 프로그래밍의 두 가지 기본적인 개념인 상속 (inheritance) 과 다형성 (polymorphism) 을 탐구합니다. 이러한 강력한 기능은 더 체계적이고 효율적이며 유연한 코드를 생성할 수 있게 해줍니다. 기존 클래스를 기반으로 새로운 클래스를 생성할 수 있게 해주는 상속부터 시작하여, 서로 다른 클래스의 객체를 통일된 방식으로 처리할 수 있게 해주는 다형성으로 넘어가겠습니다.
이 랩을 마치면 다음을 수행할 수 있습니다.
- 상속을 사용하여 클래스 계층 구조를 생성합니다.
- 하위 클래스에서 메서드를 재정의 (override) 합니다.
- 다형성을 이해하고 사용합니다.
- 추상 클래스 (abstract class) 와 메서드를 구현합니다.
이 용어들이 복잡하게 들릴지라도 걱정하지 마세요. 모든 것을 간단하고 따라하기 쉬운 단계로 나눌 것입니다. Java 프로그래밍 기술을 향상시키기 위한 흥미로운 여정을 시작해 봅시다!
기본 클래스 생성
Animal이라는 기본 클래스를 먼저 생성해 보겠습니다. 이 클래스는 다른 클래스의 기반이 될 것입니다.
터미널을 열고 프로젝트 디렉토리로 이동합니다.
cd ~/projecttouch명령을 사용하여Animal.java라는 새 파일을 생성합니다.touch Animal.java텍스트 편집기에서
Animal.java를 열고 다음 코드를 추가합니다.public class Animal { private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat() { System.out.println(name + " is eating."); } public void sleep() { System.out.println(name + " is sleeping."); } public String getName() { return name; } public int getAge() { return age; } }이 코드를 자세히 살펴보겠습니다.
name(String) 과age(int) 의 두 가지 속성을 가진Animal이라는 클래스를 정의합니다.private키워드는 이러한 속성이 클래스 내에서만 접근할 수 있음을 의미합니다.Animal객체가 생성될 때 이러한 속성을 초기화하는 생성자가 있습니다.eat()와sleep()의 두 가지 메서드가 있으며, 이는 동물이 무엇을 하는지 출력합니다.- 또한 클래스 외부에서 private 속성에 접근할 수 있도록 하는 "getter" 메서드 (
getName()및getAge()) 가 있습니다.
Animal.java파일을 저장합니다.
이제 오류가 없는지 확인하기 위해
Animal클래스를 컴파일해 보겠습니다. 터미널에서 다음을 실행합니다.javac Animal.java오류 메시지가 없으면 클래스가 성공적으로 컴파일된 것입니다!
서브클래스 생성하기
이제 기본 Animal 클래스를 만들었으니, Dog라는 서브클래스를 생성해 보겠습니다. 이는 Java 에서 상속이 어떻게 작동하는지 보여줍니다.
터미널에서
Dog.java라는 새 파일을 생성합니다.touch Dog.java텍스트 편집기에서
Dog.java를 열고 다음 코드를 추가합니다.public class Dog extends Animal { private String breed; public Dog(String name, int age, String breed) { super(name, age); // Call the superclass constructor this.breed = breed; } public String getBreed() { return breed; } }이 새로운 코드를 자세히 살펴보겠습니다.
extends Animal은Dog가Animal의 서브클래스임을 Java 에 알려줍니다.Dog는Animal로부터 상속받지만,Animal의 private 속성인name과age는Dog에서 직접 접근할 수 없습니다. 하지만Dog는 상속된 public getter 메서드인getName()과getAge()를 통해 이러한 속성에 접근할 수 있습니다.Dog에 특정한 새로운 속성인breed를 추가했습니다.- 생성자는 세 개의 매개변수를 받습니다.
super(name, age)를 사용하여Animal생성자를 호출한 다음,breed를 설정합니다. Dog에 특정한 새로운 메서드인getBreed()를 추가했습니다.
Dog.java파일을 저장합니다.Dog클래스를 컴파일합니다.javac Dog.javaAnimal.class에 대한 경고가 표시될 수 있지만, 지금은 괜찮습니다.
상속 시연
이제 Animal 및 Dog 클래스가 있으므로 상속이 어떻게 작동하는지 보여주는 프로그램을 만들어 보겠습니다.
InheritanceDemo.java라는 새 파일을 생성합니다.touch InheritanceDemo.javaInheritanceDemo.java를 열고 다음 코드를 추가합니다.public class InheritanceDemo { public static void main(String[] args) { Animal genericAnimal = new Animal("Generic Animal", 5); Dog myDog = new Dog("Buddy", 3, "Labrador"); System.out.println("Demonstrating Animal class:"); genericAnimal.eat(); genericAnimal.sleep(); System.out.println("\nDemonstrating Dog class:"); myDog.eat(); // Inherited from Animal myDog.sleep(); // Inherited from Animal System.out.println("\nDog details:"); System.out.println("Name: " + myDog.getName()); // Inherited method System.out.println("Age: " + myDog.getAge()); // Inherited method System.out.println("Breed: " + myDog.getBreed()); // Dog-specific method } }이 프로그램은
Animal및Dog클래스의 인스턴스를 모두 생성하고Dog클래스가Animal클래스에서 메서드를 상속하는 방식을 보여줍니다.InheritanceDemo.java파일을 저장합니다.프로그램을 컴파일하고 실행합니다.
javac InheritanceDemo.java java InheritanceDemo다음과 유사한 출력을 볼 수 있습니다.
Demonstrating Animal class: Generic Animal is eating. Generic Animal is sleeping. Demonstrating Dog class: Buddy is eating. Buddy is sleeping. Dog details: Name: Buddy Age: 3 Breed: Labrador이 시연은
Dog클래스가Animal클래스에서 속성과 메서드를 상속받는 동시에 자체 특정 속성 (breed) 과 메서드 (getBreed()) 를 추가하는 방법을 보여줍니다.
메소드 오버라이딩
메서드 오버라이딩은 하위 클래스가 상위 클래스에 이미 정의된 메서드의 특정 구현을 제공할 수 있도록 하는 기능입니다. 이것이 어떻게 작동하는지 살펴보겠습니다.
Dog.java를 열고 다음 메서드를 추가합니다.@Override public void eat() { System.out.println(getName() + " is eating dog food."); }이 메서드를
Dog클래스 내부에, 다른 메서드 외부 (밖) 에 추가합니다.@Override어노테이션은 컴파일러에게 상위 클래스의 메서드를 오버라이드하려는 의도가 있음을 알려줍니다. 필수는 아니지만 사용하는 것이 좋은 습관입니다.Dog.java파일을 저장합니다.이제 메서드 오버라이딩을 시연하기 위해
InheritanceDemo.java를 수정해 보겠습니다.InheritanceDemo.java를 열고 내용을 다음으로 바꿉니다.public class InheritanceDemo { public static void main(String[] args) { Animal genericAnimal = new Animal("Generic Animal", 5); Dog myDog = new Dog("Buddy", 3, "Labrador"); System.out.println("Demonstrating method overriding:"); genericAnimal.eat(); myDog.eat(); System.out.println("\nDemonstrating inherited method:"); myDog.sleep(); // This method is still inherited from Animal System.out.println("\nDog details:"); System.out.println("Name: " + myDog.getName()); System.out.println("Age: " + myDog.getAge()); System.out.println("Breed: " + myDog.getBreed()); } }InheritanceDemo.java파일을 저장합니다.업데이트된 프로그램을 컴파일하고 실행합니다.
javac Animal.java Dog.java InheritanceDemo.java java InheritanceDemo
다음과 유사한 출력을 볼 수 있습니다.
Demonstrating method overriding: Generic Animal is eating. Buddy is eating dog food. Demonstrating inherited method: Buddy is sleeping. Dog details: Name: Buddy Age: 3 Breed: Labrador이것은 메서드 오버라이딩을 통해
Dog클래스가eat()메서드의 자체 구현을 제공하면서도sleep()과 같은 다른 메서드를Animal클래스에서 상속받는 방법을 보여줍니다.
다형성 소개
다형성은 객체 지향 프로그래밍의 기본 개념으로, 기본 클래스 참조를 사용하여 하위 클래스 객체를 참조할 수 있도록 합니다. 이를 통해 더 유연하고 재사용 가능한 코드를 작성할 수 있습니다. 어떻게 작동하는지 살펴보겠습니다.
Cat.java라는 새 파일을 생성합니다.touch Cat.javaCat.java를 열고 다음 코드를 추가합니다.public class Cat extends Animal { public Cat(String name, int age) { super(name, age); } @Override public void eat() { System.out.println(getName() + " is eating fish."); } public void meow() { System.out.println(getName() + " says: Meow!"); } }이 코드는 자체
eat()메서드와 새로운meow()메서드를 가진Animal의 또 다른 하위 클래스를 생성합니다.Cat.java파일을 저장합니다.이제 다형성을 시연하기 위해
InheritanceDemo.java를 업데이트해 보겠습니다. 내용을 다음으로 바꿉니다.public class InheritanceDemo { public static void main(String[] args) { Animal[] animals = new Animal[3]; animals[0] = new Animal("Generic Animal", 5); animals[1] = new Dog("Buddy", 3, "Labrador"); animals[2] = new Cat("Whiskers", 2); System.out.println("Demonstrating polymorphism:"); for (Animal animal : animals) { animal.eat(); // This will call the appropriate eat() method for each animal } System.out.println("\nAccessing specific methods:"); ((Dog) animals[1]).getBreed(); // We need to cast to Dog to call Dog-specific methods ((Cat) animals[2]).meow(); // We need to cast to Cat to call Cat-specific methods } }이 코드는
Animal객체 배열을 생성하지만, 실제로Animal,Dog,Cat객체의 혼합을 저장합니다. 각 동물에 대해eat()을 호출하면 Java 는 객체의 실제 유형에 따라 해당 메서드의 적절한 버전을 자동으로 호출합니다.InheritanceDemo.java파일을 저장합니다.업데이트된 프로그램을 컴파일하고 실행합니다.
javac Animal.java Dog.java Cat.java InheritanceDemo.java java InheritanceDemo다음과 유사한 출력을 볼 수 있습니다.
Demonstrating polymorphism: Generic Animal is eating. Buddy is eating dog food. Whiskers is eating fish. Accessing specific methods: Whiskers says: Meow!이것은 다형성이 작동하는 방식을 보여줍니다. 모든 객체를
Animal객체로 취급할 수 있지만,eat()메서드를 호출하면 각 객체는 특정 클래스 구현에 따라 동작합니다.
요약
이 랩에서는 Java 에서 객체 지향 프로그래밍의 몇 가지 핵심 개념을 살펴보았습니다.
- 상속 (Inheritance): 기본
Animal클래스를 생성하고,Dog및Cat클래스를 파생시켰습니다. 이를 통해 코드를 재사용하고 클래스의 논리적 계층 구조를 만들 수 있었습니다. - 메서드 오버라이딩 (Method Overriding): 하위 클래스가 상위 클래스에 정의된 메서드의 자체 구현을 제공하여 보다 구체적인 동작을 가능하게 하는 방법을 살펴보았습니다.
- 다형성 (Polymorphism): 공통 상위 클래스를 통해 서로 다른 클래스의 객체를 통일적으로 처리하는 방법을 배웠으며, 이를 통해 더 유연하고 재사용 가능한 코드를 작성할 수 있었습니다.
이러한 개념은 Java 및 객체 지향 프로그래밍 전반에 걸쳐 기본입니다. 이를 통해 더 체계적이고 효율적이며 유연한 코드 구조를 만들 수 있습니다. Java 여정을 계속 진행하면서 이러한 개념이 더 복잡한 애플리케이션에서 광범위하게 사용되는 것을 발견하게 될 것입니다.
기억하세요, 이러한 개념을 마스터하는 데는 연습이 중요합니다.



