객체지향 프로그램 4대 특징 중 하나
실세계에서의 상속은 상위 객체의 속성이 하위 객체에 몰려져서 하위 객체가 상위 객체의 속성을 모두 가지는 개념
자바에서의 상속은 자식클래스가 부모클래스의속성을 물려 받고 기능을 추가하여 확장(extends)하는 개념
상속은 슈퍼클래스의 필드와 메서드를 물려 받아서 코드를 재사용 함으로써 코드 작성에 드는 시간과 비용을 줄일 수 있음
기존에 이미 잘 만들어진 클래스를 재사용하여 새로운 클래스를 생성하는 자바 문법 <- 중요!
즉, 특정 클래스를 만들 때 기존의 클래스의 데이터(속성)와 기능(메서드)을 그대로 물려 받아서 중복적인 코드를 없애줌 (클래스의 재사용, 코드의 중복을 없애줌)
자식과 부모의 관계로 형성이 되어 있음
==> 부모클래스 : Supper, Parent 클래스 라고 하기도 함
==> 자식클래스 : Sub, Child 클래스 라고 하기도 함
==> 자식은 부모의 멤버보다 같거나 많다
상속의 대상은 멤버(멤버변수, 멤버메서드)
==> 단, 생성자나 private 접근 제한을 갖는 멤버변수와 멤버메서드는 상속에서 제외
상속 시 사용되는 키워드 : extends
상속은 단일 상속만 가능 ==> 즉, 상속을 받을 수 있는 클래스는 하나다
상속의 장점은 클래스의 수정을 최소화시킬 수 있다는 점, 유지보수의 시간을 최소화시켜 준다는 점이다
형식)
[접근제한]Class 자식클래스명 extends 부모클래스명 {
......;
}
상속관계 : " ~ 은 ~ 이다" ==> is ~ a 관계
포함관게 : " ~ 은 ~ 를 가지고 있다" ==> has ~ a 관계 ==> 사람은 (name, age, id)를 가지고 있다
주의사항) 부모클래스는 반드시 기존에 미리 정의되어 있어야 함
// 부모 클래스
public class Car { // 자동차 클래스
// 멤버변수
int cc;
int door;
}
public class Sonata extends Car{
String model; // 차량 모델명
// int cc;
// int door;
void gerCarInfo() {
System.out.println("모델명 >>> "+model);
System.out.println("배기량 >>> "+cc);
System.out.println("차량 문 수 >>> "+door);
}
}
Sonata 클래스 객체 생성 과정
public class Car_01 {
public static void main(String[] args) {
Sonata sonata = new Sonata();
sonata.model = "소나타";
sonata.cc = 2000;
sonata.door = 4;
sonata.gerCarInfo();
}
}
출력결과

public class Car2 {
int cc;
int door;
String color = "검정색";
}
public class Avante extends Car2{
String color = "흰색";
// 부모의 멤버보다 자식의 멤버가 우선순위가 높다
void getCarInfo() {
System.out.println("엔진 : " + cc + ", 차량 문 수 : " + door + ", 색상 : " + color);
System.out.println("엔진 : " + cc + ", 차량 문 수 : " + door + ", 색상 : " + super.color);
// super 를 통해 부모를 불러옴
System.out.println("엔진 : " + cc + ", 차량 문 수 : " + door + ", 색상 : " + this.color);
// this 를 통해 객체 자기 자신을 불러옴
}
}
public class Car_02 {
public static void main(String[] args) {
Avante avante = new Avante();
avante.cc=1600;
avante.door=4;
avante.getCarInfo();
}
}
출력결과

public class Person {
// 멤버변수
String juminNo; // 주민번호
String name; // 이름
int age; // 나이
String job; // 직업
}
public class Employee extends Person {
int salary; // 급여
void getEmployeeInfo() {
System.out.println("주 민 번 호 >>> "+ juminNo);
System.out.println("이 름 >>> "+ name);
System.out.println("나 이 >>> "+ age);
System.out.println("직 업 >>> "+ job);
System.out.println("급 여 >>> "+ salary + "만원");
}
}
public class Student extends Person {
String major; // 학과
public Student() {
super(); // 부모클래스를 기본 생성자에 호출해줘야 오류가 안남
} // 기본 생성자
public Student(String juminNo, String name, int age, String job,String major) {
super(); // 부모클래스를 호출
this.juminNo=juminNo;
this.name=name;
this.age=age;
this.job=job;
this.major=major;
} // 인자생성자
void getStudentInfo() {
System.out.println("주 민 번 호 >>> "+ juminNo);
System.out.println("이 름 >>> "+ name);
System.out.println("나 이 >>> "+ age);
System.out.println("직 업 >>> "+ job);
System.out.println("학 과 >>> "+ major);
}
}
public class Person_03 {
public static void main(String[] args) {
// Student student = new Student();
Student student = new Student("001101-2234567", "홍길자", 25, "대학생", "영문학과");
student.getStudentInfo();
System.out.println();
Employee employee = new Employee();
employee.juminNo = "740517 - 1234567";
employee.name = "홍길동";
employee.age=51;
employee.job="회사원";
employee.salary=1000;
employee.getEmployeeInfo();
}
}
출력결과

public class Point {
int x;
int y;
public Point() { } // 기본 생성자
public Point(int x, int y) {
this.x=x;
this.y=y;
} // 인자 생성자
}
현재(자식) 클래스에서 현재 클래스 안에 있는 다른 생성자를 호출하는 명령어
형식) this(인자);
- 주의 ) this() 키워드를 사용 시애는 반드시 생성자 첫 문장에 와야 함
public class Point3D extends Point{
int z;
public Point3D() {
super(); // 부모 클래스의 기본 생성자 호출
} // 기본생성자
public Point3D(int x,int y) {
// super(); // 부모 클래스의 기본 생성자 호출 - 먼저 호출해줘야 오류 X
// this.x=x;
// this.y=y;
super(x,y); // 부모클래스의 인자 생성자 호출
} // 인자 생성자
public Point3D(int x,int y,int z) {
// this.x=x;
// this.y=y;
this(x,y); // 변수 2개짜리 인자생성자가 호출
this.z=z;
} // 인자 생성자
void output() {
System.out.println("x 좌표 >>> " + x);
System.out.println("y 좌표 >>> " + y);
System.out.println("z 좌표 >>> " + z);
}
}
public class Point_04 {
public static void main(String[] args) {
Point3D point = new Point3D(5,3,2);
point.output();
}
}
출력결과

public class Volume {
int volume = 1;
public void setVolume(int volume) {
this.volume=volume;
}
public int getVolume() {
return volume;
}
// 볼륨 올리는 메서드
void volumeUp() {
volume++;
if(volume > 15) {
volume = 15;
}
}
// 볼륨 내리는 메서드
void volumeDown() {
volume--;
if(volume < 1) {
volume = 1;
}
}
}
public class TV extends Volume{
}
public class Audio extends Volume {
}
public class Computer extends Volume {
}
import java.util.Scanner;
public class Volume_05 {
public static void main(String[] args) {
TV tv = new TV();
Audio audio = new Audio();
Computer computer = new Computer();
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("1. TV / 2. Audio / 3. Computer / 4. 종료");
System.out.print("위 메뉴 중 하나를 선택하세요 : ");
int menu = sc.nextInt();
if(menu == 4) {
break;
}
System.out.println("1. 볼륨 Up / 2. 볼륨 Down");
int volume = sc.nextInt();
switch (menu) {
case 1: // TV 메뉴 선택
if(volume == 1) {
tv.volumeUp();
}else {
tv.volumeDown();
}
break;
case 2: // Audio 메뉴 선택
if(volume == 1) {
audio.volumeUp();
}else {
audio.volumeDown();
}
break;
case 3: // Computer 메뉴 선택
if(volume == 1) {
computer.volumeUp();
}else {
computer.volumeDown();
}
break;
}
System.out.println();
System.out.println(":::::::::::::::::::::::::::::::::::::::::::::");
System.out.println("TV Volume : " + tv.getVolume()+" / "+"Audio Volume : " + audio.getVolume()+" / "+"Computer Volume : " + computer.getVolume());
}
System.out.println();
System.out.println("수고하셨습니다.");
sc.close();
}
}
출력 결과

메서드 재정의(Method Overriding)
[메서드 재정의 특징]
1. 반드시 상속 관계에서만 발생함 (메서드 다중 정의 : 동일한 클래스 내에서 발생)
2. 부모 클래스의 원형 메서드를 자식 클래스에서 재정의(다시 작성)
[메서드 재정의 조건]
1. 반드시 접근지정자, 리턴타입(반환형), 매개변수 갯수와 자료형 모두 일치해야 함
(메서드 다중정의 : 매개변수의 갯수가 다르거나, 갯수가 같다면 자료형이 달라야 함)
2. 접근 지정자는 확대 가능(축소는 불가능)
public class Animal {
void sound() {
System.out.println("소리를 냅니다.~~~");
} // sound() 메서드 end
}
public class Dog extends Animal {
// 메서드 재정의
// void sound() {
// System.out.println("멍멍멍~~~");
// }
@Override
void sound() {
System.out.println("멍멍멍~~~");
}
}
public class Cat extends Animal {
@Override
void sound() {
System.out.println("야옹야옹~~~");
}
}
public class Tiger extends Animal {
@Override
void sound() {
System.out.println("어흥어흥~~~");
}
}
public class Animal_01 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Tiger tiger = new Tiger();
dog.sound();
cat.sound();
tiger.sound();
}
}
결과 출력

부모 클래스를 자식 클래스에서 재정의하여 자식클래스의 각각의 출력문을 만들고 메인에서 모든 클래스를 불러온다
public class Shape {
void draw() {
System.out.println("그리다~~~");
}
}
public class Rectangle extends Shape {
@Override
void draw() {
System.out.println("사각형을 그리다~~~");
}
}
public class Line extends Shape {
@Override
void draw() {
System.out.println("선을 그리다~~~");
}
}
public class Circle extends Shape {
@Override
void draw() {
System.out.println("원을 그리다~~~");
}
}
public class Shape_02 {
public static void main(String[] args) {
Line line = new Line();
Circle circle = new Circle();
Rectangle rectangle = new Rectangle();
line.draw(); circle.draw(); rectangle.draw();
}
}
출력 결과

1. 완벽한 추상화를 제공한다
2. 모든 메서드가 추상화(추상 메서드)
3. 프로젝트 진행 시 표준 규약에 따른다 ==> 추상 클래스보다 더 많이 사용
4. 인터페이스는 상수와 추상메서드로만 구성이 되어 있음
5. 모든 변수는 상수가 된다
6. 모든 메서드는 추상메서드가 된다
7. 인터페이스는 객체 생성이 불가능
8. 자식 클래스로 상속을 하여 자식 클래스에서 객체 생성
==> 인터페이스의 추상 메서드는 반드시 재정의(강제성이 부여)
9. 인터페이스는 다중 상속을 제공
10. class -> interface 키워드 사용
extends -> implements 키워드 사용
※ 인터페이스 사용 목적
[인터페이스 장점]
1. 개발 시간을 단축할 수 있음
2. 표준화가 가능
public interface Inter {
int num = 50; // 인스턴스 멤버변수 - 상수
void output1(); // 추상 메서드
void output2(); // 추상 메서드
}
public class Sub implements Inter {
@Override
public void output1() {
System.out.println("인터페이스 output1 메서드 정의");
}
@Override
public void output2() {
System.out.println("인터페이스 output2 메서드 정의");
}
}
public class Inter_01 {
public static void main(String[] args) {
// 인터페이스는 객체 생성 불가능
// Inter inter = new Inter();
Sub sub = new Sub();
// static final 상수로 인식
// 상수 값을 변경하는 것은 불가능
// sub.num = 237;
sub.output1();
sub.output2();
}
}
결과 출력

- 인터페이스끼리 상속받을 경우 extends
- 클래스가 인터페이스를 상속받을 경우 implements
interface Inter1 {
void aa();
}
interface Inter2{
void bb();
}
// 인터페이스끼리 상속받을 경우 extends
interface Inter3 extends Inter1, Inter2{
// void aa(); 상속이 된 추상 메서드
// void bb(); 상속이 된 추상 메서드
void cc();
}
// 클래스가 인터페이스를 상속받을 경우 implements
class Total implements Inter3{
@Override
public void aa() {
System.out.println("aa() 추상 메서드 재정의");
}
@Override
public void bb() {
System.out.println("bb() 추상 메서드 재정의");
}
@Override
public void cc() {
System.out.println("cc() 추상 메서드 재정의");
}
}
// 인터페이스는 다중상속 가능
public class Main_02 {
public static void main(String[] args) {
Total total = new Total();
total.aa(); total.bb(); total.cc();
}
}
결과 출력

interface Camera{
// 사진 찍는 기능
void photo();
}
interface Search{
// TV보는 기능
void search();
}
interface Mp3{
// 음악 듣는 기능
void playMusic();
}
class MyPhone implements Camera, Search, Mp3{
@Override
public void playMusic() {
System.out.println("핸드폰으로 음악");
}
@Override
public void search() {
System.out.println("핸드폰으로 검색");
}
@Override
public void photo() {
System.out.println("핸드폰으로 사진");
}
}
public class Main_03 {
public static void main(String[] args) {
MyPhone myphone = new MyPhone();
myphone.playMusic();
myphone.photo();
myphone.search();
}
}
결과 출력
