상속(Inheritance) → ‘~은 ~이다’
•
기존의 클래스로 새로운 클래스를 작성하는 것(코드의 재사용)
•
두 클래스를 부모와 자식으로 관계를 맺어주는 것
•
자손은 조상의 모든 멤버를 상속 받는다(생성자, 초기화블럭 X)
•
자손의 멤버 개수는 조상보다 적을 수 없다 (자손≥조상)
•
자손의 변경은 조상에 영향을 미치지 않는다
포함(Composite) → ‘~은 ~을 가지고 있다’
•
클래스의 멤버로 참조변수를 선언하는 것
•
작은 단위의 클래스를 만들고 이 들을 조합해서 클래스를 만든다
단일 상속(Single Inheritance)
•
Java는 단일 상속만을 허용한다 (C++은 다중 상속)
•
비중이 높은 클래스 하나만 상속 관계로하고 나머지는 포함 관계로 하면 다중 상속처럼 쓸 수 있다
Object 클래스 (모든 클래스의 조상)
•
부모가 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다
•
모든 클래스는 Object 클래스에 정의된 11개의 메서드를 상속받는다
(toString, equals, hashCode...)
오버라이딩(overrinding) == 덮어쓰다
•
상속받은 조상의 메서드를 자신에 맞게 변경하는 것
•
오버라이딩 조건
1.
선언부가 조상 클래스의 메서드와 일치해야 한다
2.
접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다
3.
예외는 조상 클래스의 메서드보다 많이 선언할 수 없다 (조상 ≥ 자식)
오버로딩 vs 오버라이딩
참조변수 super
•
객체 자신을 가리키는 참조변수
•
인스턴스 메서드, 생성자 내에만 존재
•
조상의 멤버를 자신의 멤버와 구별할 때 사용
(변수가 하나라면 this, super 둘 다 같은 값)
조상의 생성자 super()
•
조상의 생성자를 호출할 때 사용
•
조상의 멤버는 조상의 생성자를 호출해서 초기화
•
자식 클래스에서 조상 클래스의 멤버를 초기화하면 안된다
•
생성자의 첫 줄에는 반드시 생성자를 호출해야 한다
(안하면 컴파일러가 super(); 삽입해줌)
패키지(package)
•
서로 관련된 클래스의 묶음
•
클래스는 클래스 파일, 패키지는 폴더, 하위 패ㅣ지는 하위 폴더
•
클래스의 실제 이름은 패키지를 포함
(ex. java.lang.String)
•
rt(runtime).jar는 클래스들을 압축한 파일
java9부터 module개념으로 인해 없어짐
패키지의 선언
•
패키지는 소스파일의 첫번째 문장으로 단 한 번 선언
•
같은 소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다
•
패키지 선언이 없으면 이름없는 패키지에 속하게 된다
클래스 패스(classpath)
•
클래스 파일의 위치를 알려주는 경로
•
환경변수 classpath로 관리하며 경로 간 구분자는 ‘;’ 사용해 등록해야함
import문
•
클래스를 사용할 때 패키지이름을 생략할 수 있다
•
java.lang 패키지의 클래스는 import 하지않아도 된다
•
패키지문과 클래스선언 사이에 선언한다
•
이름이 같은 클래스가 속한 두 패키지를 import하면 클래스 앞에 패키지명을 붙여줘야한다
static import문
•
static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다
제어자(modifier)
•
클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
•
접근 제어자
public, protected, (default), private 중 1
•
그 외
static, final, abstract, native, transient, synchronized, volatile, strictfp
•
접근 제어자만 가장 앞에 딱 1개를 쓰고 그 외 제어자는 여러 개 쓸 수 있다
static - 클래스의, 공통적인
final - 마지막의, 변경될 수 없는
abstract - 추상의, 미완성의
•
추상 클래스를 상속 받아서 완전한 클래스로 만든 후에 객체 생성 가능
접근 제어자(access modifier)
•
접근 제어자를 사용하는 이유
1.
외부로부터 데이터를 보호하기 위해서
(직접접근X, 메서드를 통한 간접접근O)
2.
외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서
3.
유지보수를 용이하게 하기 위해서
→ 캡슐화
다형성(Polymorphism)
•
여러 가지 형태를 가질 수 있는 능력
•
조상 타입 참조 변수로 자손 타입 객체를 다루는 것
•
객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이
•
자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다
참조변수의 형변환
•
사용할 수 있는 멤버의 개수를 조절하는 것
•
조상, 자손 관계의 참조변수는 서로 형변환 가능
•
실제 가리키는 인스턴스가 중요하다!!!!!!
instanceof 연산자
•
참조변수의 형변환 가능여부 확인에 사용 (가능하면 true)
•
형변환 전에 반드시 instanceof로 확인해야 함
•
조상, 자신으로 변환하는건 가능!
매개변수의 다형성
•
참조형 매개변수는 메서드 호출시 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다
여러 종류의 객체를 배열로 바꾸기
•
조상타입의 배열에 자손들의 객체를 담을 수 있다
추상 클래스(abstract class)
•
미완성 설계도. 미완성 메서드를 갖고 있는 클래스
•
다른 클래스 작성에 도움을 주기 위한 것으로 인스턴스 생성 불가
•
추상 클래스도 생성자가 있어야 한다
•
상속을 통해 추상 메서드를 완성해야 인스턴스 생성가능
추상 메서드(abstract method)
•
미완성 메서드. 구현부(몸통, {})가 없는 메서드
•
꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우
•
추상 클래스에 추상 메서드를 다 구현하지 않으면 abstract를 꼭 붙여야 한다
추상 클래스를 사용하는 이유 → 쉬운 설계도 작성
•
코드의 중복을 제거한다
•
단계별로 추상 클래스를 구체화시켜 변경을 쉽게 한다
인터페이스(interface)
•
추상 메서드의 집합
•
구현된 것이 전혀 없는 설계도. 껍데기(모든 멤버가 public)
•
추상 메서드와 상수만 사용할 수 있다
•
public, abstract, static, final은 생략할 수 있다
인터페이스의 상속
•
인터페이스의 조상은 인터페이스만 가능하다(Object가 최고 조상이 아님)
•
다중 상속이 가능하다(추상메서드는 충돌해도 문제가 되지 않는다)
인터페이스의 구현
•
인터페이스에 정의된 추상 메서드를 완성하는 것
•
상속으로 추상 클래스를 구현하는 것과 같다!! (extends 대신 implements 쓰는 것만 다름)
•
추상 메서드를 전부 구현하지 않았다면 클래스 앞에 abstract를 붙여야 한다
인터페이스를 이용한 다형성
•
인터페이스도 클래스의 부모처럼 사용할 수 있다.
•
이걸 통해서 다중 상속의 효과를 낼 수 있다
•
하지만 클래스의 객체가 많아도 인터페이스에 추상 메서드 밖에 쓸 수 없다
•
인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능하다
인터페이스의 장점
•
두 대상(객체) 간의 ‘연결, 대화, 소통'을 돕는 ‘중간 역할'을 한다
ex) GUI, 윈도우 등..
•
선언(설계)와 구현을 분리시킬 수 있게 한다
•
인터페이스 덕분에 B가 변경되어도 A는 안바꿀 수 있게 된다 (느슨한 결합)
•
개발 시간을 단축할 수 있다
•
변경에 유리한 유연한 설계가 가능하다
•
표준화가 가능하다
•
서로 관계없는 클래스들을 관계를 맺어줄 수 있다
디폴트 메서드
•
인터페이스에 추가된 기능 (jdk1.8 부터)
•
기존 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어렵다는 문제를 해결
•
디폴트 메서드는 인스턴스 메서드 (인터페이스의 원칙을 위반)
default를 앞에 꼭 붙여주어야 하고 뒤에 {} 몸통을 붙여야 함
•
디폴트 메서드가 기존의 메서드와 충돌할 때 해결책 → 직접 오버라이딩!!!!
1.
여러 인터페이스의 디폴트 메서드 간의 충돌 → 디폴트 메서드를 오버라이딩
2.
디폴트 메서드와 조상 클래스의 메서드 간의 충돌 → 조상 클래스의 메서드가 상속, 디폴트 메서드는 무시
내부 클래스(inner class)
•
내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다
•
코드의 복잡성을 줄일 수 있다 (캡슐화)
내부 클래스의 종류와 특징
•
내부 클래스의 종류와 유효범위(scope)는 변수와 동일
내부 클래스의 제어자와 접근성
•
내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
그냥 클래스에서는 default와 public만 가능
내부 클래스에서는 default, public, private, protected 다 가능
•
static 멤버를 정의하려면 무조건 static 클래스여야 한다
•
같은 클래스 내에서 인스턴스 멤버가 static 멤버를 쓰는건 가능
같은 클래스 내에서 static 멤버가 인스턴스 멤버를 쓰는건 불가능
•
지역 클래스는 지역 클래스 내에서만 사용 가능!!!
•
외부 클래스의 private 멤버는 내부 클래스에서 사용 가능
•
지역 내부 클래스를 감싸고 있는 메서드의 상수만 사용 가능
(jdk 1.8부터는 final이 안 붙어도 값이 바뀌지 않으면 상수로 인식 → final 생략 가능)
•
외부 클래스 밖에서 내부 클래스의 사용 방법
1.
인스턴스 내부 클래스
외부 클래스의 인스턴스를 먼저 생성하고 내부 클래스의 인스턴스를 생성해서 사용한다
2.
static 내부 클래스
외부 클래스의 인스턴스를 생성하지 않아도 되지만 외부 클래스의 이름은 붙여준다
3.
내부 클래스의 지역 메서드
내부 클래스의 인스턴스를 생성한 후 사용
•
같은 변수명 구별법
익명 클래스(anonymous class)
•
이름이 없는 일회용 클래스로 정의와 생성을 동시에 한다
Q&A
•
한 부모클래스를 여러 자식클래스가 상속받으면 메모리공간은 여러개가 되는건가?
부모클래스에 x,y라는 멤버가 여러개?
지역 변수가 final이 붙은 상수만 접근할 수 있는 이유
•
지역 변수가 소멸해도 constant pool에 등록된 상수를 계속 사용하기 위함