본문 바로가기
프로그래밍 언어/JAVA

07. 상속과 인터페이스

by zieunee 2019. 2. 8.
반응형

    간단 차이점 정리

    Implement, extends 차이
    • extends : 부모로부터 상속/ 클래스를 확장하기 위한 것( 클래스는 선언과 내용이 들어가 있는 것 )
    • implements :조언자로부터 상속 / 다중 상속을 통해 해결 가능함 / 그러나 interface로 정의되어 있어야함

    intertace ,
    abstract , extends
    차이
    • intertace : 한자식이 두 부모로 부터 상속받을 수 있음 (그자체로 객체를 만들 수 없음 ) implements로 상속해서 객체를 만들 수 있음 ,, 인터페이스의 함수를 필수적으로 장착해야함
    • abstract 는 자식이 부모의 것을 쓸때 공통적인것들을 사용하기 위해 추상적으로 틀+기능을 구현해 놓은것 >> 자식이 해당 클래스를 상속받아 자유롭게 extends 하여 override해서 쓸 수 있음
    • extends 부모로부터 물려받는것
    • 상속은 물려받는것 , 인터페이스는 장착하는것

07. 상속과 인터페이스

리팩토링

겹치는 함수를 별도의 클래스에 만들고 각각 클래스에 가져다 쓴다.

"o is a ㅁ" 관계이면 중복코드 제거를 할 수 있다.

단일상속

자바는 단일 상속이다.

상속이란?

Employee, Professor , Student 클래스에서 Person클래스의 내용을 가져다 사용하는것을 '상속한다' 라고 표현한다.

접근제한자 class 클래스명 extends 부모 클래스명{

}

상속 전

Employee.java

package com.ruby.java.ch07;

public class Employee {

private String name; // 외부에서 쓸 수 있게 끔 getter setter 만들어줌
private int age;
private String dept;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getDept() {
return dept;
}

public void setDept(String dept) {
this.dept = dept;
}

@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", dept=" + dept + "]";
}

}

Porfessor.java

package com.ruby.java.ch07;

public class Professor {
private String name; // 외부에서 쓸 수 있게 끔 getter setter 만들어줌
private int age;
private String subject;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSubject() {
return subject;
}

public void setSubject(String subject) {
this.subject = subject;
}

@Override
public String toString() {
return "Professor [name=" + name + ", age=" + age + ", subject=" + subject + "]";
}


}

Student.java

package com.ruby.java.ch07;

public class Professor {
private String name; // 외부에서 쓸 수 있게 끔 getter setter 만들어줌
private int age;
private String subject;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSubject() {
return subject;
}

public void setSubject(String subject) {
this.subject = subject;
}

@Override
public String toString() {
return "Professor [name=" + name + ", age=" + age + ", subject=" + subject + "]";
}


}

MainTest.java

package com.ruby.java.ch07;

public class MainTest {
public static void main(String[] args) {

Student s = new Student();
Employee e = new Employee();
Professor p = new Professor();

s.setName("홍길동");
s.setAge(47);
s.setMajor("컴퓨터 과학");

e.setName("이기자");
e.setAge(35);
e.setDept("입학처");

p.setName("이순신");
p.setAge(47);
p.setSubject("빅데이터");


System.out.println(s.toString());
System.out.println(e.toString());
System.out.println(p.toString());



}
}


상속 후-

Person.java

package com.ruby.java.ch07.inheritance;

public class Person {
private String name;
private int age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public String toString() {
return name + ":"+ age;
}

}

Employee.java

package com.ruby.java.ch07.inheritance;

public class Employee extends Person{
private String dept;

public String getDept() {
return dept;
}

public void setDept(String dept) {
this.dept = dept;
}

}

Professor.java

package com.ruby.java.ch07.inheritance;

public class Professor extends Person {
private String subject;

public String getSubject() {
return subject;
}

public void setSubject(String subject) {
this.subject = subject;
}

}

Student.java

package com.ruby.java.ch07.inheritance;

public class Student extends Person{
private String major;

public String getMajor() {
return major;
}

public void setMajor(String major) {
this.major = major;java
}

}

MainTest.java

package com.ruby.java.ch07.inheritance;

public class MainTest {
public static void main(String[] args) {

// TODO Auto-generated constructor stub
Student s = new Student();
Employee e = new Employee();
Professor p = new Professor();

s.setName("홍길동");
s.setAge(47);
s.setMajor("컴퓨터 과학");

e.setName("이기자");
e.setAge(35);
e.setDept("입학처");

p.setName("이순신");
p.setAge(47);
p.setSubject("빅데이터");


System.out.println(s.toString());
System.out.println(e.toString());
System.out.println(p.toString());

}
}

new Employee() --->Employee---->Person를 가서 Person에 있는 name age 의 변수 와 함수등을 가져와서 다시 Person ----> Employee ----> new Employee()로 간다.

p281

부모것이 먼저 만들어 지고 그 다음 자식이 만들어 진다.

Person 에서 상속받은것 , Employee 자기자신에서 만든것 순이다.

Person (name | age | getName() ...) + Employee (dept | getDept() | setDept() )

p282

상속활용

메서드 오버라이딩

  • 부모한테 상속받은 메서드의 내용을 재정의 하는 것

  • 부모클래스에서 정의된 메서드(바디)를 자식클래스에서 재정의함

위에 코드 Student Employee Professor 에서 출력값에서는 자식 클래스가 선언한 값(서로 다 결과를 반환하는 값들)이 안나온다.

why? Person.java에 안써져있기 때문!

-> 그래서 각각 Student Employee Professor파일에 재정의해야한다!

각각 자식클래스에

@Override
public String toString() {
return "...";
}

추가

ex>

//Employee.java
@Override
public String toString() {

//return name + ":" + age + ":"+ dept;
//에러난다. 상속받은 것이기 때문! (x)
       
       return  this.getName() + ":" + this.getAge() + ":"+ this.getDept();
       //이렇게 해주어야함

}

super

상속해도 너무 길고 중복되는것 많아! -> 그래서 super를 쓴다.

extends 다음에 있는애를 지칭한다.

super.메서드명(인자)

위에 코드에서 각각 자식 클래스 toString()함수에

return super.toString() +":"+dept; // Emloyee.java
return  super.toString() +":"+subject; // Professor.java
return  super.toString() +":"+ major; // Student.java

로 바꿔준다.

부모 생성자 호출

각각 클래스에 기본 생성자를 만든다.

public Person() {
   super();
System.out.println("Person() 호출");
}// Person.java

public Employee(){
super();
   System.out.println("Employee() 호출");
}// Emloyee.java

public Professor() {
   super();
   System.out.println("Professor() 호출");
}// Professor.java

public Student() {
super();
   System.out.println("Student() 호출");
  }// Student.java

결과값(출력)

Person()  호출
Student()  호출
Person()  호출
Employee() 호출
Person()  호출
Professor()  호출

Student Employee Professor 이 생성될때마다 부모클래스의 생성자도 같이 호출된다.


전)

Student Employee Professor 각각에 저 생성자를 다 만들어 줘야 했다.

public Student(String name, int age, String major){
setName(name);
setAge(age);
this.major=major;

}

후)

중복을 줄이기 위해서 부모클래스 Person.java에서 생성자 하나를 만들어 준 후

    public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}

super(name,age); 로 만들어주면 중복을 줄일 수 있다.

public Student(String name, int age, String major){
super(name,age);
this.major=major;

}


final 제어자

final : 값을 못바꾸게 하는것

메서드 앞에 final 주면 오버라이딩 불가하다

추상개념

Employee

|

Salesman -- Manager -- Consultant

|

Director

메서드 정의할 때 앞에다

제어자 리턴타입 메서드이름(매개변수){ 바디 } 가있음

바디가 필요없어서 안만들으면 오류!

그럴때 일부러 바디 안만들었어! 라고 abstract 키워드를 주면 오류가 나지 않는다.

absrtact class Employee{
   String name;
   int salary;
public absrtact void calcSalary();
}

추상 메서드를 가지고 있으면 class에서도 추상메서드 가지고 있다고 말해야한다.

추상메서드는 왜쓰나요?

내가 가지고 있는 내용중에 반드시 오버라이딩 시키고 싶다(오버라이딩는 선택사항) 할때 쓰는 것이 abstract

반드시 오버라이딩 시키고 싶다 ! 바디 일부러 안만들고! 드러나게 하고 싶다! 할 경우 abtract

public abstract class Employee {
String name;
int salary;

public abstract void calcSalary();

}

Employee 상속받으면 에러뜸

public class Salesman extends Employee {
} // error!

---> 오버라이딩 시켜줘야한다!!

public class Salesman extends Employee {
@Override
public void calcSalary() {

} //오류 사라짐!
}

무조건 오버라이딩 시켜줘야하는데 해주기 싫다면?

자신 클래스도 추상화 시켜주면 된다.

public abstract class Salesman extends Employee {
//오버라이딩 안시켜줘도됨
int salary;
String name;
}

인터페이스

어떤 프로그램을 개발할 떄 아이폰/갤럭시용 프로그램을 만들어야한다. 그랬을 때 아이폰용은 별도의 사용방법으로 사용할 수 있게하고 , 갤럭시도 갤럭시대로 방법이 있다. 사용자는 한가지 방법으로만 사용할 수 있게끔 만들고 싶다. 어느 플랫폼이나 공통적으로 기능을 구현 할 때 강제 규약(표준화)을 만들면 편해진다.

제어자 interface 인터페이스명{

public static final 변수선언;
public abstract 메서드선언();
public default 메서드선언() {}; //최신버젼 필요 ㄴㄴ
public static 메서드선언() {}; //최신버젼 필요 ㄴㄴ
public private 메서드선언() {}; //최신버젼 필요 ㄴㄴ

}

interface Test{//추상메서드를 가지고 있는 객체가 interface
   public static final int MIN_SIZE = 1;
   void a(); // 추상메서드
   void b(); // 추상메서드
}

Class A{
a(){};
b(){};
}
Class B{
   a(){};
   b(){};
   A.c = new A();
   c.a();
   c.b();
}

인터페이스 안에서 변수선언을 한다면? 인스턴스 변수는 선언할 수 없다

 public static final int MIN_SIZE = 1;

으로 앞에 붙여줘야 한다.

메서드를 선언할 때에도

public abstract String getMessage();

로 abstract 를 추가해야 한다.

p319

클래스 다이어그램

<<interface>>

클래스가 클래스를 상속하면 : 실선

클래스가 인터페이스 상속 : 점선

제어자 class 클래스명 extends 부모 클래스명 implements 인터페이스명,인터페이스명..{

}

다중상속이 가능하다


인터페이스 안에서만 만들목적으로 쓴 것이 private 이다.



인터페이스는 body를 만들지 않고 메서드만 만들어 놓기 때문에 단순히 정의만 해두고 구체적인 내용이 없다

그에 반해서 class 는 완전한 body 를 가지고 있기 때문에 extend로 상속 받아서 사용해야한다.



반응형

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

09. 기본 API활용하기  (0) 2019.02.11
08. 다형성과 내부클래스  (0) 2019.02.11
06. 객체지향 구현  (0) 2019.02.08
05.객체지향  (0) 2019.02.07
04. 배열  (0) 2019.02.07