클래스 간의 관계 2가지
· 상속 : 두 클래스를 부모와 자식으로 관계를 맺어주는 것 ('~은 ~이다. (is-a)')
· 포함 : 클래스의 멤버로 참조변수를 선언하는 것 ('~은 ~을 가지고 있다.(has-a)'
상속과 포함 구별 방법
단일 상속
class TvDVD extends Tv, DVD {
}
위와 같은 다중 상속은 불가능 하다.
예시로 Tv, DVD에서 메서드 이름은 같고 내용은 같을 때 어떤 것을 상속해야 하는지 충돌이 나기 때문에
Object 클래스 - 모든 클래스의 조상
오버라이딩의 조건
1. 선언부가 조상 클래스의 메서드와 일치해야 함.
2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음.
3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없음.(같거나 적어야 함)
참조변수 super
- 객체 자신을 가리키는 참조변수. 인스턴스 메서드내에만 존재
- 조상의 멤버를 자신의 멤버와 구별할 때 사용
super() - 조상의 생성자
- 생성자의 첫 줄에 반드시 생성자를 호출해야 함
- 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입
접근 제어자를 사용하는 이유
: 외부로부터 데이터를 보호하기 위해서
: 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
다형성
- 여러 가지 형태를 가질 수 있는 능력
- 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
Tv t = new SmartTv(); // 타입 불일치
자손 타입의 참조변수로 조상 타입 객체를 가리킬 수 없다.
: 리모콘에는 해당 기능이 있지만 실제로 해당 기능에 대한 멤버가 없으므로 에러가 남.
참조변수의 형변환
- 사용할 수 있는 멤버의 갯수를 조절하는 것
- 조상, 자손 관계의 참조변수는 서로 형변환 가능
car의 멤버는 4개 이고
FireEngine의 멤버는 5개임
Car c = new Car();
FireEngine fe = (FireEngine) c; // 형변환 실행 에러
fe.water(); // 컴파일 오케이
//실제 인스턴스는 car의 4개 밖에 없으니까
instanceof 연산자
- 참조변수의 형변환 가능여부 확인에 사용, 가능하면 true 반환
- 형변환 전에 반드시 instanceof로 확인해야 함
FireEngine fe = new FireEngine();
System.out.println(fe instanceof Object); //true
System.out.println(fe instanceof Car); //true
System.out.println(fe instanceof FireEngine); //true
참조변수의 형변환 하는 이유
: 참조변수(리모컨)을 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서
매개변수의 다형성
추상 클래스
- 미완성 설계도. 미완성 메서드를 갖고 있는 클래스
추상 메서드를 통해서 자손 클래스에서 해당 메서드를 구현하도록 강제성 부여함
추상 메서드에서도 인스턴스 메서드 생성 가능
: 추상 클래스는 객체 생성 불가함, 자손 객체가 구현되어야 하므로 인스턴스메서드도 그때서야 사용 가능
추상클래스의 작성
: 여러 클래스에 공통적으로 사용 될 수 있는 추상클래스를 바로 작성하거나
기존 클래스의 공통 부분을 뽑아서 추상클래스를 만듦.
인터페이스
: 추상 메서드의 집합
구현된 것이 전혀 없는 설계도. (모든 멤버가 public)
추상클래스와 인터페이스 차이
: 추상 클래스는 일반 클래스인데 추상 메서드를 가지고 있음(iv포함)
인터페이스는 추상 메서드만 있는 집합
public, abstract 생략 가능
인터페이스의 상속
- 인터페이스의 조상은 인터페이스만 가능
- 다중 상속이 가능
인터페이스의 구현
- 인터페이스에 정의된 추상 메서드를 완성하는 것
인터페이스 작성
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.(단, static 메서드와 디폴트 메서드는 예외)
인터페이스 구현이란 :
인터페이스 자체로 인스턴스 생성할 수 없다, 자신의 몸통을 만들어주는 클래스를 작성해야 함 (implements)
인터페이스의 추상메서드 몸통{}만들기(미완성 설계도 완성하기)
class Fighter implements Fightable {
public void move(int x, int y){}
public void attack(Unit u){}
}
일부만 구현할 경우, 클래스 앞에 abstract를 붙여야 함
abstract class Fighter implements Fightable {
public void move(int x, int y){}
}
오버라이딩 할 때는 조상의 메서드보다 넓은 범위의 접근 제어자를 지정해야 하므로
Fighter클래스에서는 접근 제어자를 무조건 public으로 해야 함
인터페이스의 장점
- 두 대상 간의 '연결, 대화, 소통'을 돕는 중간 역할을 한다.
-선언(설계)와 구현을 분리시킬 수 있게 한다.
A-B 직접적인 관계를
A-I-B 간접적인 관계로 바뀜
-> 나중에 B가 바뀌어도 A에게 영향을 안 미침, 즉 독립적임
-표준화가 가능
ex) jdbc가 인터페이스 집합임, mysql이나 orcale 등 DB들이 변경되어도 애플리케이션은 거의 변경이 없음
서로 관계없는 클래스들을 관계를 맺어줄 수 있다.
디폴트 메서드와 static 메서드
- 인터페이스에 디폴트 메서드, static 메서드 추가 기능
- 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움
: 인터페이스 구현한 클래스들이 모두 새로운 메서드를 추가해야 하니까
추상 메서드 구현해야 하는 부담감을 없애줌
내부 클래스
장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다(캡슐화)
class A {
}
class B {
}
// 를 아래와 같이 내부클래스로 변경
class A{
class B{
}
}
익명 클래스
new 조상클래스이름(){
}
or
new 구현인터페이스이름() {
}
class InnerEx{
public static void main(String[] args){
Button b = new Button("Start");
b.addActionListener(new EventHandler());
}
}
class EventHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("ActionEvent occurred!!");
}
}
아래 코드는 익명 클래스 이용해서 변환
class InnerEx{
public static void main(String[] args){
Button b = new Button("Start");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
System.out.println("ActionEvent occurred!!");
}
}
}
}
아래 코드는 안드로이드 앱 만들때 구현한 코드 일부인데 내부 클래스가 이런식으로 사용된다.
'자바 스터디' 카테고리의 다른 글
[자바의 정석] CH 9(Math ~ Objects) (0) | 2023.06.29 |
---|---|
[자바의 정석] CH8 (0) | 2023.06.24 |
[자바의 정석] CH-6 (0) | 2023.05.04 |
[자바의 정석] CH-5 ~ CH-6 (0) | 2023.04.27 |
[자바의 정석] CH3 ~ CH4 (0) | 2023.03.30 |