Java의 상속, 오버라이드, 오버로드, 그리고 객체 형변환의 개념과 실습 예제를 통해 학습한 내용을 정리해보았습니다. 이 과정에서 배운 기술과 문제 해결 방법을 공유하며, 실력을 쌓기 위해 노력한 과정을 보여드리고자 합니다.
상속은 기존 클래스의 속성과 기능을 새로운 클래스에서 재사용할 수 있게 해주는 개념입니다. 이를 통해 코드의 중복을 줄이고, 코드의 재사용성을 높일 수 있습니다.
1-2. 오버라이드란?
부모 클래스에 정의된 것과 동일한 이름을 갖는 메서드를 자식 클래스가 정의한 경우,
부모 클래스의 기능은 자식에게 가려진다.
이렇게 부모의 기능을 재정의 하는 것을 메서드 Override라 한다.
[오버라이드 첫번째 코드]
package override;
// Hello 클래스: 부모 클래스
class Hello {
// say 메서드: 기본 구현
public void say() {
System.out.println("Hello");
}
}
// English 클래스: Hello 클래스를 상속받는 자식 클래스
class English extends Hello {
// Hello 클래스로부터 say 메서드를 상속받지만, 특별히 재정의하지 않음
}
// Korean 클래스: Hello 클래스를 상속받고 say 메서드를 오버라이드
class Korean extends Hello {
// 부모 클래스의 say 메서드를 오버라이드하여 재정의
@Override
public void say() {
super.say(); // 부모 클래스의 say 메서드 호출
System.out.println("안녕하세요"); // 자식 클래스에서 추가한 기능
}
}
public class Main01 {
public static void main(String[] args) {
// English 객체 생성: 부모 클래스의 say 메서드를 상속받아 사용
English e = new English();
e.say(); // "Hello" 출력
System.out.println();
// Korean 객체 생성: 부모 클래스의 say 메서드를 오버라이드하여 사용
Korean k = new Korean();
k.say(); // 부모 클래스의 say 메서드 + "안녕하세요" 출력
}
}
[오버라이드 2번째 코드]
package override;
// Parent 클래스: 부모 클래스
class Parent {
// Parent 클래스의 생성자
// 문자열 메시지를 받아서 콘솔에 출력
public Parent(String msg) {
System.out.println(msg);
}
}
// Child 클래스: Parent 클래스를 상속받는 자식 클래스
class Child extends Parent {
/*
자식 클래스의 생성자는 부모 클래스의 생성자를 호출해야 한다.
- 부모 클래스에 정의된 생성자를 호출하기 위해 super 키워드를 사용한다.
- super(msg)는 부모 클래스의 생성자를 호출하여 전달받은 msg 파라미터를 전달한다.
- 이 방식은 부모 클래스와 자식 클래스 간의 생성자 호출 관계를 명확히 한다.
*/
// Child 클래스의 생성자
// 부모 클래스의 생성자에 전달할 msg 파라미터를 받아서 super()를 통해 부모에게 전달
public Child(String msg) {
super(msg); // 부모 클래스의 생성자를 호출하여 메시지를 출력
}
}
public class Main02 {
public static void main(String[] args) {
// Child 객체를 생성하면서 "자식"이라는 메시지를 전달
// 이 메시지는 Parent 클래스의 생성자에서 출력된다.
Child c = new Child("자식");
}
}
[Unit이 부모 클래스이고 Army,Navy,AirForce 각각의 자식 클래스이면 메인메서드로 출력하는 코드]
package override;
/*
Unit 클래스: 공통적인 특성을 가지는 부모 클래스
*/
public class Unit {
private String name; // 유닛의 이름을 저장하는 변수
// Unit 클래스의 생성자
public Unit(String name) {
super(); // 최상위 클래스인 Object의 생성자를 호출 (생략 가능)
this.name = name; // name 필드 초기화
}
// 유닛의 이름을 반환하는 메서드
public String getName() {
return name;
}
// 유닛의 이름을 설정하는 메서드
public void setName(String name) {
this.name = name;
}
/*
* 기본 공격 메서드
* 유닛의 이름과 "공격준비" 메시지를 출력
*/
public void attack() {
System.out.println(this.name + " >> 공격준비");
}
}
package override;
/*
Army 클래스: Unit 클래스를 상속받아 육군을 나타내는 자식 클래스
*/
public class Army extends Unit {
// Army 클래스의 생성자
public Army(String name) {
super(name); // 부모 클래스의 생성자를 호출하여 이름을 설정
}
/*
* attack 메서드를 오버라이드하여 지상 공격 메시지를 출력
*/
@Override
public void attack() {
super.attack(); // 부모 클래스의 attack 메서드 호출
System.out.println(super.getName() + " >> 지상곡격 실행!");
}
/*
* 육군의 특수 기능인 탱크 공격을 출력
*/
public void tank() {
System.out.println(super.getName() + " >> 탱크공격!!");
}
}
package override;
/*
Navy 클래스: Unit 클래스를 상속받아 해군을 나타내는 자식 클래스
/
public class Navy extends Unit {
/
Navy 클래스의 생성자
/
public Navy(String name) {
super(name); // 부모 클래스의 생성자를 호출하여 이름을 설정
}
/*
* attack 메서드를 오버라이드하여 해상 공격 메시지를 출력
*/
@Override
public void attack() {
super.attack(); // 부모 클래스의 attack 메서드 호출
System.out.println(super.getName() + " >> 해상공격 실행");
}
/*
* 해군의 특수 기능인 핵 미사일 공격을 출력
*/
public void nucleus() {
System.out.println(super.getName() + " >> 핵 미사일");
}
}
package override;
/*
AirForce 클래스: Unit 클래스를 상속받아 공군을 나타내는 자식 클래스
*/
public class AirForce extends Unit {
/*
* AirForce 클래스의 생성자
*/
public AirForce(String name) {
super(name); // 부모 클래스의 생성자를 호출하여 이름을 설정
}
/*
* attack 메서드를 오버라이드하여 공중 공격 메시지를 출력
*/
@Override
public void attack() {
super.attack(); // 부모 클래스의 attack 메서드 호출
System.out.println(super.getName() + " >> 공중곡격 실행");
}
/*
* 공군의 특수 기능인 폭격을 출력
*/
public void booming() {
System.out.println(super.getName() + " >> 폭격");
}
}
package override;
/**
Main03 클래스: 프로그램의 실행을 담당하는 메인 클래스
*/
public class Main03 {
public static void main(String[] args) {
// Army 객체를 생성하고 "육군"이라는 이름을 설정
Army am = new Army("육군");
am.attack(); // 육군의 공격 메시지를 출력
am.tank(); // 육군의 탱크 공격 메시지를 출력
System.out.println();
// Navy 객체를 생성하고 "해군"이라는 이름을 설정
Navy na = new Navy("해군");
na.attack(); // 해군의 공격 메시지를 출력
na.nucleus(); // 해군의 핵 미사일 공격 메시지를 출력
System.out.println();
// AirForce 객체를 생성하고 "공군"이라는 이름을 설정
AirForce af = new AirForce("공군");
af.attack(); // 공군의 공격 메시지를 출력
af.booming(); // 공군의 폭격 메시지를 출력
}
}
package overload;
public class Character {
// 필드: 직업을 저장하는 문자열 변수
private String job;
// 필드: 나이를 저장하는 정수 변수
private int age;
/*
* 직업을 설정하는 메서드.
*/
public void setProperty(String job) {
this.job = job;
}
/*
* 나이를 설정하는 메서드.
*
*/
public void setProperty(int age) {
this.age = age;
}
/*
* 직업과 나이를 동시에 설정하는 메서드.
*/
public void setProperty(String job, int age) {
this.job = job;
this.age = age;
}
/*
* 나이와 직업을 동시에 설정하는 메서드. (순서가 다름)
*/
public void setProperty(int age, String job) {
this.age = age;
this.job = job;
}
/**
* Character 객체의 정보를 문자열로 반환합니다.
*/
@Override
public String toString() {
return "Character [job=" + job + ", age=" + age + "]";
}
}
package overload;
public class Main01 {
public static void main(String[] args) {
// Character 객체 생성
/*
* 각 setProperty의 데이터형이 다르다
*/
Character c = new Character();
// 초기 상태의 Character 객체 출력
System.out.println(c.toString());
// 나이만 설정하고 출력
c.setProperty(30);
System.out.println(c.toString());
// 직업만 설정하고 출력
c.setProperty("개발자");
System.out.println(c.toString());
// 직업과 나이를 동시에 설정하고 출력
c.setProperty(20, "자영업");
System.out.println(c.toString());
// 직업과 나이를 동시에 설정하고 출력 (순서가 다름)
c.setProperty("교수", 40);
System.out.println(c.toString());
}
}