Java
[Final] Abstract Classes
ssungni
2024. 5. 7. 11:21
Abstract Classes
- Classes are more general as we move up the in heritance hierarchy
// 클래스는 상속 계층 구조를 통해 위로 올라갈수록 더 일반적임 - Inheritance is useful to definecommonattributes/behaviour
// 상속은 공통 속성이나 동작을 정의하는 데 유용 - ex) Animal Class
추상 클래스는 일반적인 동작이나 속성을 정의하고, 이 클래스를 상속받아 구체적인 클래스를 만들 때 사용됨.
추상 클래스는 abstract 키워드를 사용하여 정의되며, 추상 메서드(abstract method)를 포함할 수 있음.
여기서 makeSound() 메서드는 추상 메서드로 선언되었기 때문에, 이 클래스를 상속받는 실제 동물 클래스에서는 makeSound() 메서드를 반드시 구현해야 함.
// 추상 클래스 Animal abstract class Animal { private String name; private int age; // 생성자 public Animal(String name, int age) { this.name = name; this.age = age; } // 추상 메서드 - 각 동물마다 구현해야 할 메서드 public abstract void makeSound(); // 일반 메서드 public void eat() { System.out.println(name + "이(가) 먹이를 먹습니다."); } // 일반 메서드 public void sleep() { System.out.println(name + "이(가) 잠을 잡니다."); } }
이제 실제 동물 클래스를 상속받아 구현해보면
// 실제 동물 클래스 - Cat class Cat extends Animal { public Cat(String name, int age) { super(name, age); } // 추상 메서드 구현 @Override public void makeSound() { System.out.println("야옹"); } } // 실제 동물 클래스 - Dog class Dog extends Animal { public Dog(String name, int age) { super(name, age); } // 추상 메서드 구현 @Override public void makeSound() { System.out.println("멍멍"); } }
Cat 클래스와 Dog 클래스는 Animal 추상 클래스를 상속받아 구현된 실제 동물 클래스임.
각각의 동물 클래스는 makeSound() 메서드를 재정의(override)하여 각 동물의 소리를 표현하는 것을 볼 수 있음
Motivation (계기)
- A common method can't bedefinedinthesuper class
// super class에서 common method를 정의할 수 없는 경우 - abstract 키워드를 사용하여 abstract classes와 methods 선언
- ex) Person super class, Employee and Stdent sub classes
// 추상 클래스 Person public abstract class Person { private String name; private int age; // 생성자 public Person(String name, int age) { this.name = name; this.age = age; } // 추상 메서드 - 구현이 없는 메서드 public abstract void introduce(); }
// Employee 클래스 - Person을 상속받음 public class Employee extends Person { private String employeeId; // 생성자 public Employee(String name, int age, String employeeId) { super(name, age); this.employeeId = employeeId; } // 추상 메서드 구현 @Override public void introduce() { System.out.println("저는 직원입니다."); } } // Student 클래스 - Person을 상속받음 public class Student extends Person { private String studentId; // 생성자 public Student(String name, int age, String studentId) { super(name, age); this.studentId = studentId; } // 추상 메서드 구현 @Override public void introduce() { System.out.println("저는 학생입니다."); } }
- Instance를 생성할 수는 없음.
위의 Main 클래스에서는 Person 추상 클래스의 인스턴스를 직접 생성할 수 없음. 대신 Employee와 Student 클래스의 인스턴스를 생성하여 Person 타입의 참조 변수로 참조할 수 있음.public class Main { public static void main(String[] args) { // Person person = new Person("John", 30); // 추상 클래스이므로 인스턴스 생성 불가능 Person employee = new Employee("Jane", 25, "E123"); // Employee 클래스의 인스턴스 생성 employee.introduce(); // "저는 직원입니다." 출력 Person student = new Student("Mike", 20, "S456"); // Student 클래스의 인스턴스 생성 student.introduce(); // "저는 학생입니다." 출력 } }
Abstract Methods
- abstract classes를 사용하여
- 클래스는 추상 및 구체적인 메서드를 모두 포함할 수 있음
- 구체적인 하위 클래스에서 반드시 재정의되어야 함. 그렇지 않으면 하위 클래스도 추상 클래스여야 함
public class Dog extends Animal ... public abstract class Cat extends Animal { public Cat(String name) { super(name); } // Cat 클래스는 추상 메서드를 재정의하지 않으므로 추상 클래스가 됨 }
- Abstract classes and Polymorphism
- Polymorphism(다형성)
- 같은 코드를 사용하여 다양한 객체를 다룰 수 있는 기능을 말함.
- 상속과 관련하여 부모 클래스 타입의 참조 변수가 자식 클래스의 객체를 참조할 수 있는 성질을 의미함.
- 메서드 오버라이딩(재정의)을 통해 다형성을 구현할 수 있음
- ex)
public class Dog extends Animal public void makeSound() { System.out.println(getName() + "이(가) 멍멍 짖습니다."); public class Cat extends Animal public void makeSound() { System.out.println(getName() + "이(가) 야옹 웁니다."); public class Main { public static void main(String[] args) { Animal dog = new Dog("멍멍이"); Animal cat = new Cat("야옹이"); animalMakesSound(dog); animalMakesSound(cat); } // 다형성을 이용한 동물 소리 출력 메서드 public static void animalMakesSound(Animal animal) { animal.makeSound(); } }
- Polymorphism(다형성)
Object Class
- 모든 Java 클래스의 부모 클래스
- 다른 클래스들은 암시적으로 이 클래스를 상속받음
- 일부 메서드
- equals(): 객체의 동등성을 비교하는 메서드
더보기public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } // equals() 메서드 재정의 @Override public boolean equals(Object obj) { if (this == obj) { return true; // 같은 객체인 경우 true 반환 } if (obj == null || getClass() != obj.getClass()) { return false; // null이거나 클래스가 다른 경우 false 반환 } Person other = (Person) obj; // obj를 Person으로 형변환 return age == other.age && name.equals(other.name); // 필드 값 비교 } public static void main(String[] args) { Person person1 = new Person("John", 30); Person person2 = new Person("John", 30); System.out.println(person1.equals(person2)); // true 출력 (내용 비교) } }
- hashCode(): 객체의 해시 코드를 반환하는 메서드
더보기public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public int hashCode() { return Objects.hash(name, age); // 필드 값들을 이용하여 해시 코드 생성 } public static void main(String[] args) { Person person = new Person("Alice", 25); System.out.println(person.hashCode()); // 객체의 해시 코드 출력 } }
- toString(): 객체를 문자열로 표현하는 메서드
더보기public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } public static void main(String[] args) { Person person = new Person("Bob", 35); System.out.println(person.toString()); // 객체의 문자열 표현 출력 } }
- equals(): 객체의 동등성을 비교하는 메서드
Downcasting
- 부모 클래스에서 실제 자식 클래스 타입으로의 형변환
- Example
- Using "instanceof"