Java 8일차 : 상속, 다형성, 인터페이스
상속
class 서브클래스명 extends 수퍼클래스명{
...
}
- this. : 현재 자신의 주소를 가지고 있는 인스턴스 변수
- super. : 수퍼클래스의 주소를 가지고 있는 인스턴스 변수
- 서브클래스 생성시 생성자로 값을 받아 수퍼클래스로 넘긴다.
- 이 때, 접근이 가능한 변수는 super. 얻으면 되는데, 만약 private 이면 직접 줄 수가 없으니 부모생성자를 호출하여 넘긴다. (단, 이때 부모 생성자 안의 내용이 본인(부모)의 private변수에 대한 처리가 있어야 한다.)
- 부모생성자 호출 : super() => 반드시 첫줄에 있어야 한다.
this() : 현재 클래스의 생성자호출
super() : 부모 클래스의 생성자호출
예시
package test.day0412;
class Apple1{
String msg;
Apple1(String msg){
this.msg = msg;
}
public Apple1() {
System.out.println("부모클래스의 디폴트생성자 ");
}
}
class Orange1 extends Apple1{
String carName;
int price;
Orange1(String msg, String carName, int price) {
//기본적으로 super()은 항상 내부적으로 실행되므로 1. 부모클래스에 디폴트생성자를 만들던지, 2. super(msg)라 주든지.
//super();
super.msg = msg; //super는 부모의 주소를 가지고 있는 인스턴스 변수
//super의 멤버변수는 변수이름이 중복되지 않는한 super, this로 모두 접근 가능
this.carName = carName;
this.price = price;
}
public void write() {
System.out.println(super.msg);
System.out.println(this.carName);
System.out.println(this.price);
}
}
public class SuperEx1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Apple1 ap = new Apple1();
Orange1 or = new Orange1("호호호", "소나타", 2000);
or.write();
System.out.println(or.msg); //부모의 변수지만 자식에게서 호출도 되는군?
}
}
package test.day0412;
class Apple1{
String msg;
Apple1(String msg){
this.msg = msg;
}
public Apple1() {
System.out.println("부모클래스의 디폴트생성자 ");
}
}
class Orange1 extends Apple1{
String carName;
int price;
Orange1(String msg, String carName, int price) {
//기본적으로 super()은 항상 내부적으로 실행되므로 1. 부모클래스에 디폴트생성자를 만들던지, 2. super(msg)라 주든지.
//super();
super.msg = msg; //super는 부모의 주소를 가지고 있는 인스턴스 변수
//super의 멤버변수는 변수이름이 중복되지 않는한 super, this로 모두 접근 가능
this.carName = carName;
this.price = price;
}
public void write() {
System.out.println(super.msg);
System.out.println(this.carName);
System.out.println(this.price);
}
}
public class SuperEx1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Apple1 ap = new Apple1();
Orange1 or = new Orange1("호호호", "소나타", 2000);
or.write();
System.out.println(or.msg); //부모의 변수지만 자식에게서 호출도 되는군?
}
}
클래스의 멤버변수가 모두 private 일 경우 서브클래스에서 접근하기
package test.day0412;
class Apple2{
private String msg;
private int day;
Apple2(){
System.out.println("수퍼클래스의 디폴트 생성자 ");
msg = "default";
day=1;
}
Apple2(String msg, int day){
System.out.println("수퍼클래스의 두번째 생성자 ");
this.msg = msg;
this.day = day;
}
public void writeData() {
System.out.println("메세지= " + msg);
System.out.println("날짜= " + day);
}
}
class Orange2 extends Apple2{
private String carName;
Orange2(){
System.out.println("서브클래스의 디폴트 생성자 ");
carName = "그랜져";
}
Orange2(String msg, int day, String carName){
super(msg, day); //반드시 첫줄
this.carName = carName;
}
@Override
public void writeData() {
// TODO Auto-generated method stub
super.writeData();
//부모의 변수가 private이라 직접 불러오기 거시기하므로
//미리 부모클래스에서 자기 변수를 public메서드안에서 한번씩 불러주면
//그 메시드를 자식에서 호출하는건 가능함. 즉 간접적으로 부모의 private변수를 가져오려면 이렇게...
System.out.println("차종= " + carName);
}
}
public class SuperEx2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Orange2 or2 = new Orange2();
or2.writeData();
Orange2 or1 = new Orange2("오늘은 금요일", 12, "벤츠");
or1.writeData();
}
}
오버라이딩
- 자식의 오버라이딩 메서드는 접근지정자가 부모의 그것보다 항상 같거나 넓어야함
package test.day0412;
class Apple3{
protected void hello1() {
System.out.println("super hello1");
}
void hello2() {
System.out.println("super hello2");
}
}
class Orange3 extends Apple3{
@Override
protected void hello1() { //public과 protected만 가능
System.out.println("sub hello1");
}
@Override
void hello2() { //public, protected, default 가능
System.out.println("sub hello2");
}
}
public class SuperEx3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Orange3 or3 = new Orange3();
or3.hello1();
or3.hello2();
}
}
Final
package test.day0412;
//class가 final이면 상속불가능 (자식 만들기 불가능)
final class Apple4{
//메서드가 final이면 (자식클래스로부터) 오버라이딩이 안된다.
final public void write() {
}
}
다형성
다형성의 조건
-
-
반드시 상속관계가 성립되어야 한다.
부모클래스 변수명 = new 자식클래스();
-
일반적으로 중복제거 및 재사용성을 위해 메서드의 인자를 지정할 때 다형성을 많이 적용한다
-
부모클래스 변수 하나로 많은 자식 클래스들을 관리하기 위해서 사용한다
-
A a = new B(); 로 선언되었을 때 호출 가능한 메서드는
-
- A가 가진 메서드
-
- 오버라이드 된 메서드
-
- 불가능 : B에만 구현되어있는 메서드
-
예시
package test.day0412;
abstract class SuperPlay{
public void play() {
System.out.println("super");
}
//play2가 직접적으로 하는일이 없다.
//그래서 등록만 하고 싶을 때 미완성의 메서드라는 의미로 앞에 abstract를 붙다.
//이때 클래스의 멤버중에 한개라도 abstract가 있다면
//클래스도 반드시 abstract라야 한다. (추상 메서드는 추상 클래스에만 존재 가능)
//method body없이 ; 로 끝낸다.
//추상클래스를 상속받은 클래스는 반드시 추상 메소드를 오버라이드하여야 한다.
//만약 안할경우 그 자식클래스 역시 추상화해줘야한다.
//추상 클래스는 직접적으로 객체 생성이 불가능.
abstract public void play2();
}
class Draw extends SuperPlay{
@Override
public void play() {
System.out.println("drawing!");
}
@Override
public void play2() {
System.out.println("drawing again!");
}
}
class Piano extends SuperPlay{
@Override
public void play() {
super.play();
System.out.println("playing piano!!");
}
@Override
public void play2() {
System.out.println("piano again!");
}
}
class SuperEx5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
SuperPlay sp = null;
sp = new Draw();
sp.play();
sp.play2();
sp = new Piano();
sp.play();
sp.play2();
//sp = new SuperPlay(); 추상 클래스는 객체 생성이 안된
}
}
package test.day0412;
abstract class Apple6{
public static void show() {
System.out.println("super abstract");
}
abstract public void disp(); //추상 메서드. 메서드 바디가 없다.
}
//Apple6 를 상속받을 자식 클래스가 추상클래스가 아니라면 반드시 disp를 오버라이드 해야함
class Orange6 extends Apple6{
public void disp() {
System.out.println("disp methos is overridden");
}
}
public class AbstEx6 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Apple6 ap = new Orange6();
ap.disp();
ap.show();
}
}
- 추상 클래스로부터 상속받는 클래스가 추상메서드를 오버라이드 하지 않으면 같이 추상화를 해줘야한다
- 상속시 반드시 오버라이드 할 필요는 없고(추상화만 해준다면) 언젠가 후손클래스가 필요할 때 오버라이드 하면 된다.
package test.day0412;
abstract class Apple7{
public static void show() {
System.out.println("super abstract");
}
abstract public void disp();
}
abstract class Orange7 extends Apple7{
public void show2() {
System.out.println("orange7 super");
}
abstract public void add();
}
class Kiwi7 extends Orange7{
@Override
public void add() {
// TODO Auto-generated method stub
System.out.println("add data");
}
@Override
public void disp() {
// TODO Auto-generated method stub
System.out.println("display data");
}
}
public class AbstEx7 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Apple7 ap = new Kiwi7();
ap.disp();
ap.show();
Orange7 ap2 = new Kiwi7();
ap2.add();
ap2.disp();
ap.show();
ap2.show2();
}
}
인터페이스
- 일단 일반 메서드와 추상 메서드가 섞여 있을 경우에는 추상 클래스로 구현하면 된다.
- 하지만, 만약 모든 메서드가 추상 메서드라면 굳이 클래스를 유지할 필요가 없다.
- 그냥 클래스 말고 인터페이스로 만들면 된다. 인터페이스란 상수와 추상메서드로만 이루어져 있는것을 말한다
interface 인터페이스명{ 메서드, 상수,... }
-
인터페이스는 음식점의 메뉴판과 같다. 왜냐하면 실체는 없고 선언만 되어 있으므로..
-
인터페이스 상속
// 1. 클래스가 인터페이스를 상속(구현)받을 경우 class 클래스명 implements 인터페이스명{ //이경우 인터페이스가 가진 모든 메소드를 오버라이딩하여야한다 ... } // 2. 인터페이스를 인터페이스가 상속받을 경우 interface 서브인터페이스명 extends 슈퍼인터페이스명{ ... }
예시
package test.day0412;
//인터페이스는 상수, 추상 메서드로만 구성
interface InterA{
// final int SPEED=100;
// abstract public void speedUp();
int SPEED=100;
public void speedUp();
//이렇게 줘도 알아서 상수, 알아서 abstract method로 읽
}
//인터페이스를 상속받는 클래스는 반드시 모든 메서드를 오버라이드 해줘야한다
class Car implements InterA{
@Override
public void speedUp() {
// TODO Auto-generated method stub
System.out.println("현재속도" + SPEED + "에서 업!");
}
}
class Car2 implements InterA{
int speed = SPEED;
@Override
public void speedUp() {
// TODO Auto-generated method stub
speed += 20;
System.out.println("속도 " +SPEED+ "에서 " + speed + "로 스피드업!" );
}
}
public class InterfaceEx8 {
public static void main(String[] args) {
// TODO Auto-generated method stub
InterA it = new Car();
it.speedUp();
InterA it2 = new Car2();
it2.speedUp();
}
}
-
하나의 클래스에서 여러개의 인터페이스를 구현할(상속받을)수 있다
class A implements B,C,D { ... } //만약 B가 클래스, C,D가 인터페이스라면 class A extends B implements C,D { ... }
예시
package test.day0412;
interface One{
public void play();
public void draw();
}
//인터페이스 간에도 상속이 가능하다.
interface Two extends One{
public void study();
}
class Three{
public void write() {
System.out.println("wirte");
}
}
class Four extends Three implements Two{
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("play");
}
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("draw");
}
@Override
public void study() {
// TODO Auto-generated method stub
System.out.println("study");
}
}
public class InterfaceEx9 {
public static void main(String[] args) {
// TODO Auto-generated method stub
One one = new Four();
one.play();
one.draw();
Two two = new Four();
two.draw();
two.play();
two.study();
Three three = new Four();
three.write();
}
}
package test.day0412;
interface InterAA{
public void play();
}
interface InterBB{
public void draw();
}
class Milk implements InterAA, InterBB{//인터페이스는 다중구현(상속)가능
@Override
public void draw() {
// TODO Auto-generated method stub
System.out.println("draw!");
}
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("play!");
}
}
public class InterfaceEx10 {
public static void main(String[] args) {
InterAA a1 = new Milk();
a1.play();
InterBB a2 = new Milk();
a2.draw();
Milk a3 = new Milk();
a3.draw();
a3.play();
}
}
실습문제
[다형성에 대한 문제]
Command -write =>인터페이스
상속받은 클래스들(오버라이드 메소드)
List -write
Delete -write
Modify -write
Insert -write
================================
메인에서
Command com=null; <- 변수는 얘만 선언하세요
조건에 따라
com=new List();
com=new Delete();
..등등으로 생성한후 write 호출하세요
[메 뉴] : 추가, 삭제, 출력, 수정, 종료
import java.util.Scanner;
interface Command
{
public void write();
}
class List implements Command{
@Override
public void write() {
// TODO Auto-generated method stub
System.out.println("게시판에 전체 게시물을 출력합니다");
}
}
class Insert implements Command{
@Override
public void write() {
// TODO Auto-generated method stub
System.out.println("게시판에 게시글을 추가합니다");
}
}
class Delete implements Command{
@Override
public void write() {
// TODO Auto-generated method stub
System.out.println("게시판에 게시글을 삭제합니다");
}
}
class Modify implements Command{
@Override
public void write() {
// TODO Auto-generated method stub
System.out.println("게시판에 게시글을 수정합니다");
}
}
public class InterfaceEx11 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int num=0;
Command com = null;
while(true)
{
System.out.println("[메뉴]\n1.추가\n2.삭제\n3.출력\n4.수정\n5.종료\n");
num=sc.nextInt();
switch(num)
{
case 1:
com = new Insert(); break;
case 2:
com=new Delete(); break;
case 3:
com=new List(); break;
case 4:
com=new Modify(); break;
default:
System.out.println("종료합니다");
System.exit(0);
}
com.write();//어떤 객체로 생성이 됐는냐에 따라 하는일이 달라진다
}
}
}
Comments