자바 객체지향 정리

병호·2025년 1월 30일

자바

목록 보기
24/24

클래스와 객체

클래스 : 객체를 정의해 놓은 것, 객체를 생성하기 위해 사용한다.
객체 : 실제로 존재하는 것. 사물 또는 개념. 객체가 가지고 있는 기능과 속성에 따라 용도가 다르다. 객체 = 속성(변수) + 기능(메서드)

즉, 클래스는 객체를 만들기 위해 필요하고 객체는 객체가 가지고 있는 기능과 속성을 사용하기 위해 필요하다.

클래스 작성 방법

클래스 앞의 접근 제어자로는 public, default(아무것도없음)이 가능하다.

public class가 있는 경우는 소스파일의 이름이 반드시 public class의 이름과 일치해야 한다.

public class가 아무것도 없는 경우는 default class 아무 이름이나 가능하다.

하나의 클래스에는 public class가 하나만 존재 가능하다.

하나의 소스파일에는 하나의 클래스만 작성하는 것이 바람직하다.

객체의 생성과 사용

1. 객체의 생성

클래스명 변수명; // 클래스의 객체를 참조하기 위한 참조변수 선언
변수명 = new 클래스명(); // 클래스의 객체를 생성한 후, 객체의 주소를 참조변수에 저장

ex) Tv t = new Tv();

2. 객체의 사용

객체를 사용한다는 의미는 객체가 가지고 있는 변수, 메서드를 사용한다는 것을 의미한다.

ex) t.channel = 7; // Tv 인스턴스의 멤버변수 channel에 7을 저장.
t.channelDown(); // Tv 인스턴스의 메서드 호출.

Tv t1 = new Tv();
Tv t2 = new Tv();
t1.channel = 7;
t2.channel = 0;

위에서 t2 = t1; 이라는 문장을 넣으면 어떻게 될까??

t2가 가리키는 객체는 t1이 가리키는 객체로 바뀐다. 즉, 참조하는 주소값이 바뀐다. 그러므로 t2.channel = 7이 된다. 그리고 아무도 참조하지 않는 t2 객체는 GC가 수거해간다.

1)하나의 인스턴스를 두 개 이상의 참조변수가 가리키는 것은 가능.
2)하나의 참조변수로 두 개 이상의 인스턴스를 가리키는 것은 불가능.

객체 배열

객체배열은 참조변수 배열이다.

Tv t1, t2, t3; -> Tv[] tvArr = new Tv[3]; (Tv타입 참조변수 x3)

참조변수의 기본값은 null이므로 생성되면 자동 초기화.

객체배열은 객체를 담기 위한 것이므로 객체를 생성해서 배열의 각 요소에 저장한다.
ex) tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
Tv[] tvArr = {new Tv(), new Tv(), new Tv()};

new라는 키워드를 통해서 객체를 Heap이라는 메모리 영역에 메모리를 할당해주고 메모리 주소를 반환한 후 생성자를 실행시켜줌.

클래스의 정의

(1)클래스 = 데이터 + 함수

  1. 변수 : 하나의 데이터를 저장할 수 있는 저장 공간.
  2. 배열 : 같은 종류의 여러 데이터를 저장할 수 있는 저장 공간.
  3. 구조체 : 서로 관련된 여러 데이터(종류, 관계 x)를 하나로 저장할 수 있는 저장 공간.
  4. 클래스 : 데이터와 함수의 결합.(구조체 + 함수)

함수(메서드) : 어떤 하나의 작업을 하는 명령문들의 묶음.

(2)클래스 = 사용자 정의 타입

int hour;
int minute;
int second;

위 대신

class Time {
int hour;
int minute;
int second;
}

Time t = new Time();

위와 같이 객체로 생성해서 나타내는 것이 더 간편하다. 즉, 클래스는 관련있는 것을 사용자가 정의해서 생성할 수 있다.

선언위치에 따른 변수 종류

영역에 따른 변수 종류 - 1. 클래스 영역( iv - 인스턴스 변수, cv - 클래스 변수(static + iv) )
2. 메서드 영역(lv)

클래스 영역 = 클래스 시작부터 끝
메서드 영역 = 메서드 시작부터 끝

클래스 영역에는 선언문만 가능하다. (System.out.println(), y = x + 3 과 같은 문장들은 들어가지 못함)

변수에 따른 생성시기 - 클래스 변수 : 클래스가 메모리에 올라갈 때
인스턴스 변수 : 인스턴스가 생성되었을 때
지역 변수 : 변수 선언문이 수행되었을 때

클래스 변수는 객체 생성 없이 사용가능, 인스턴스 변수는 객체를 생성해야지만 사용가능하다.

클래스 변수와 인스턴스 변수

클래스 변수 : 모든 인스턴스가 공통으로 가져야 하는 속성
인스턴스 변수 : 인스터스 개별 속성

  • 사용법
    인스턴스 변수 : 인스턴스이름.변수이름
    클래스 변수 : 클래스이름.변수이름

메서드란?

메서드 = 선언부 + 구현부
1. 문장들을 작업단위로 묶어놓은 것.(코드의 중복 제거)
2. 값(입력)을 받아서 처리하고, 결과를 반환(출력)

ex) int(반환타입) add(메서드이름)(int x, int y (매개변수)) {
int result = x + y;
return result;
}

  • 메서드의 장점 : 코드의 중복을 줄일 수 있음, 코드의 관리가 쉬움, 코드를 재사용할 수 있다, 코드가 간결해서 이해하기 쉬워진다.

  • 메서드의 작성 : 반복적으로 수행되는 여러문장을 메서드로 작성, 하나의 메서드는 하나의 기능만 수행하도록 작성.

메서드의 호출

메서드의 이름(값1, 값2 ... );

print99danAll(); // void print99danAll()을 호출
int result = add(2, 3); // int add(int x, int y)를 호출하고, 결과를 result에 저장

return문

실행중인 메서드를 종료하고 호출한 곳으로 되돌아간다.

리턴타입을 생략가능한 경우는 void일때만 가능하다.

  • 반환값
    int add(int x, int y) {
    int result = x + y;
    return result;
    }

반환타입이 void가 아닐 때, result와 return타입인 int가 일치하지 않더라도, int형으로 형변환가능한 char나 byte같은 타입들은 자동형변환 되므로 가능하다.

호출스택

메서드 수행에 필요한 메모리가 제공되는 공간
메서드가 호출되면 호출스택에 메모리 할당, 종료되면 해제

기본형 매개변수

기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.

ex)

class Data {int x};
class Ex_6 {
	public static void main(String[] args) {
    	Data d = new Data();
        d.x = 10;	// Data 객체의 변수 x에 10 저장
        System.out.println("main() : x = " + d.x);
        
        change(d.x);	// change메서드 호출, 매개변수에 Data객체 변수 x를 넣음
        System.out.println("After change(d.x)");
        System.out.println("main() : x = " + d.x);
   }
   static void change(int x) {
   		x = 1000;	// 여기서 바꾸는 x는 Data객체의 x가 아닌 change 메서드의 지역변수 x 
        System.out.println("change() : x = " + x);
   }
}   

참조형 매개변수

참조형 매개변수는 변수의 값을 읽고, 변경 가능하다.

class Data {int x};
class Ex_6 {
	public static void main(String[] args) {
    	Data d = new Data();	// Data 객체 생성
        d.x = 10;	// Data 객체의 변수 x에 10 저장
        System.out.println("main() : x = " + d.x);
        
        change(d);	// change 메서드의 매개변수에 Data 인스턴스 d를 넣어서 호출
        System.out.println("After change(d)");
        System.out.println("main() : x = " + d.x);
   }
   static void change(Data d) {	// change 메서드, 매개변수로 Data객체를 넣는다. 이는 원래 있던 d 객체의 참조값을 복사해서 매개변수로 넣는다.
   		d.x = 1000;	// 객체 d의 변수 x를 10에서 1000으로 변경한다. 
        System.out.println("change() : x = " + d.x);
   }
}   

static 메서드와 인스턴스 메서드

인스턴스 메서드 :
1. 인스턴스 생성 후, '참조변수.메서드이름()'으로 호출
2. 인스턴스 멤버(iv, im)과 관련된 작업을 하는 메서드
3. 메서드 내에서 인스턴스 변수 사용 가능

static 메서드 :
1. 객체 생성 없이, '클래스이름.메서드이름()'으로 호출 가능
2. 인스턴스 멤버와 관련 없는 작업을 하는 메서드
3. 메서드 내에서 인스턴스 변수 사용 불가

인스턴스 메서드와 static 메서드의 차이 : 인스턴스 변수(iv)의 사용 여부

  • static을 언제 붙여야 할까?
  1. 속성 중에서 공통 속성에 붙인다.
  2. iv,im을 사용하지 않는 메서드에 붙인다.
  • 메서드 간의 호출과 참조
class TestClass2 {
	int iv;				// 인스턴스 변수
    static int cv;		// 클래스 변수
    
    void instanceMethod() {	// 인스턴스 메서드
    	System.out.println(iv);	// 인스턴스 변수 사용가능(인스턴스 메서드는 객체 생성 후 사용가능하므로 객체 생성 후 사용가능한 인스턴스 변수도 사용가능하다.)
        System.out.println(cv);	// 클래스 변수 사용가능(클래스 변수는 클래스가 메모리에 로드된 후 생성되므로 언제든 사용가능하다.)
    }
    
    static void staticMethod() {	// static 메서드
    	System.out.println(iv);	// 인스턴스 변수 사용불가(인스턴스 변수는 객체 생성 후 사용되는데 static 메서드는 객체 생성하지 않고도 사용가능하므로 인스턴스 변수 사용 시, 객체가 생성되있는지 불분명하므로 사용불가능하다.)
        System.out.println(cv);	// 클래스 변수 사용가능
    }
}

인스턴스 메서드는 인스턴스 변수, static 변수 및 메서드 모두 사용가능하지만 static 메서드는 인스턴스 변수, 메서드는 사용 불가능하다.

오버로딩

한 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것.

  • 오버로딩 성립 조건
  1. 메서드 이름이 같아야 함
  2. 매개변수의 개수 및 타입이 달라야 함
  3. 리턴 타입은 상관 없음

생성자, 기본 생성자

생성자란 인스턴스가 생성될 때마다 호출되는 '인스턴스 초기화 메서드'

  • 생성자(iv 초기화 메서드)
  1. 이름이 클래스 이름과 같아야 한다.
  2. 리턴값이 없다.(void 안붙임)
  3. 모든 클래스는 반드시 생성자를 가져야 한다.

기본생성자 : 매개변수가 없는 생성자. 생성자가 없을 때만, 컴파일러가 자동 추가해줌.

생성자 this(), 참조변수 this

  • 생성자 this()
  1. 생성자에서 다른 생성자 호출할 때 사용
  2. 다른 생성자 호출 시, 첫줄에서만 가능
  • 참조변수 this
  1. 인스턴스 자신을 가리키는 참조변수
  2. 인스턴스 메서드(생성자 포함)에서만 사용가능
  3. 지역변수(lv)와 인스턴스 변수(iv)를 구별할 때 사용

this는 인스턴스 자신을 가리키는 참조변수로 인스턴스 변수의 주소가 들어있다.
this(), this(매개변수)는 생성자로 같은 클래스의 다른 생성자를 호출할 때 사용한다.

변수의 초기화, 멤버변수의 초기화

  1. 변수의 초기화
  • 지역변수(lv)는 수동 초기화해야함.(사용전 꼭!!)
  • 멤버변수(iv, cv)는 자동 초기화된다.
  1. 멤버변수의 초기화
  • 명시적 초기화(=)
  • 초기화 블럭(인스턴스 초기회 블럭: {}, static 초기화 블럭: static {} 둘 다 여러문장 넣기 가능)
  1. 생성자

정리
cv, iv 초기화 방법에는 3가지 방법이 있다.
1) 자동초기화 : 0으로 초기화됨
2) 간단초기화 : =으로 초기화한다
3) 복잡초기화 : {}, static {}, 생성자로 초기화한다, 주로 iv초기화 시 생성자를 사용하고 cv 초기화 시 static {}을 사용한다. {}는 잘 사용하지 않는다.

클래스 변수 초기화 시점 : 클래스가 처음 로딩될 때 한번
인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때마다

초기화 순서 : cv -> iv, 자동 -> 간단 -> 복잡 순으로 초기화됨.

상속

기존의 클래스로 새로운 클래스를 작성하는 것(코드의 재사용)
두 클래스를 부모와 자식 관계로 맺어주는 것
자손은 조상의 모든 멤버를 상속받는다(생성자, 초기화블럭 제외)
자손의 멤버 개수는 조상보다 적을 수 없다(같거나 많다)
자손의 변경은 조상에 영향을 미치지 않는다

클래스간의 관계, 상속과 포함

클래스의 관계 - 1. 상속, 2. 포함

포함이란? - 클래스의 멤버로 참조변수를 선언하는 것.

class Point {
	int x;
    int y;
}

class Circle {
	Point p = new Point();	// 원점
    int r;	// 반지름
}    

작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다.

  • 클래스간의 관계 결정하기
  1. 상속관계 : '~은 ~이다'
  2. 포함관계 : '~은 ~을 가지고 있다.'

단일상속, Object 클래스

  • Java는 단일상속만을 허용한다.
  • 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다.
  • Object클래스 - 모든 클래스의 조상
    부모가 없는 클래스는 자동적으로 Object클래스를 상속받음.
    모든 클래스는 Object클래스에 정의된 11개의 메서드를 상속받는다.
    toString(), equals(), hashCode(), ...

오버라이딩

  • 상속받은 조상의 메서드를 자신에 맞게 변경하는 것.
class Point {
	int x;
    int y;
    
    String getLocation() {
    	return "x =" + x + ",y =" + y;
    }
}

class point3D extends Point {
	int z;
    
    String getLocation() {		// 오버라이딩
    	return "x =" + x + ",y =" + y + ",z =" + z;
    }
}    

선언부 변경불가. 내용만 바꿀 수 있음.

  • 오버라이딩의 조건
  1. 선언부가 조상클래스의 메서드와 일치해야 한다.
  2. 접근제어자를 조상클래스의 메서드보다 좁은 범위로 변경할 수 없다.
  3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
  • 오버로딩 vs 오버라이딩
    오버로딩 : 기존에 없는 이름이 같은 새로운 메서드를 정의하는 것.
    오버라이딩 : 상속받은 메서드의 내용을 변경하는 것.

참조변수 super, 생성자 super()

  • 참조변수 super
    객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에서만 존재
    조상의 멤버를 자신과 구분할 때 사용
class Ex7_2 {
	public static void main(String[] args) {
    	Child c = new Child();
        c.method();
    }
}

class Parent { int x = 10; }	// super.x
class Child extends Parent {
	int x = 20;	// this.x
    
    void method() {
    	System.out.println("x=" + x);
        System.out.println("this.x=" + this.x);
        System.out.println("super.x=" + super.x);
    }
}    

// x = 20, this.x = 20, super.x = 10
  • 조상의 생성자 - super()
    조상의 생성자를 호출할 때 사용
    조상의 멤버는 조상의 생성자를 호출해서 초기화
    생성자와 초기화블럭은 상속이 안됨

  • 조건
    생성자의 첫 줄에는 반드시 생성자를 호출해야 한다. (중요)
    그렇지 않으면 컴파일러가 생성자의 첫 줄에 super()를 자동으로 삽입

패키지

패키지 : 서로 관련된 클래스들의 묶음, 폴더
클래스의 진짜 이름은 패키지를 포함
rt.jar는 클래스들을 압축한 파일(JDK 설치경로\jre\lib에 위치)
jar파일은 클래스파일들을 묶어놓은 것(압축파일)

  • 패키지의 선언
    패키지는 소스파일의 첫번째 문장으로 단 한번 선언
    같은 소스 파일의 클래스들은 모두 같은 패키지에 속한다
    패키지 선언이 없으면 이름없는 패키지에 속하게 된다

import문, static import문

import문 : 클래스를 사용할 때 패키지 이름을 생략할 수 있다.
java.lang 패키지의 클래스는 import하지 않고 사용할 수 있다.(String, Object, System, Thread...)

  • import문의 선언
  1. import 패키지명.클래스명; 또는 import 패키지명.*;

import문은 패키지 선언과 클래스 선언 사이에 선언한다.
import문은 컴파일 시 처리되므로 프로그램의 성능에 영향없음.

static import문 : static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.

ex)

import static java.lang.Integer.*;
import static java.lang.Math.random;
import static java.lang.System.out;

System.out.println(Math.random()) -> out.println(random());

제어자 static, final, abstract

제어자 : 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여

  • 접근 제어자 : public, protected, (default), private
  • 그 외 : static, final, abstract, native, synchronized, volatile...

하나의 대상의 여러 제어자를 같이 사용가능(접근 제어자는 하나만)

  • static - 클래스의, 공통적인
    대상 : 멤버변수, 메서드
  1. 멤버변수에 붙이면 : 모든 인스턴스에 공통적으로 사용가능한 클래스 변수가 된다.
  2. 메서드에 붙이면 : 인스턴스를 생성하지 않고 호출이 가능한 클래스 메서드가 된다.
  • final - 마지막의, 변경될 수 없는
    대상 : 클래스, 메서드, 멤버변수, 지역변수

ex)

final class FinalTest {	// 조상이 될 수 없는 클래스
	final int MAX_SIZE = 10;	// 값을 변경할 수 없는 멤버변수(상수)
    
    final void getMaxSize() {	// 오버라이딩 할 수 없는 메서드(변경 불가)
    	final int LV = MAX_SIZE;	// 값을 변경할 수 없는 지역변수(상수)
        return MAX_SIZE;
    }
}    
  • abstract - 추상의, 미완성의
    대상 : 클래스, 메서드

ex)

abstract class AbstractTest {	// 추상 클래스(추상 메서드를 포함한 클래스)
	abstract void move();	// 추상 메서드(구현부가 없는 메서드)
}    

추상클래스의 인스턴스는 생성 불가.
추상클래스는 상속을 통해 완전한 클래스를 만든 후에 객체 생성 가능.

접근제어자

private : 같은 클래스 내에서만 접근 가능하다.
(default) : 같은 패키지 내에서만 접근 가능하다.
protected : 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이 가능하다.
public : 접근 제한이 전혀 없다.

위 4개 중 하나만 사용가능.

  • 클래스에는 접근제어자 public, (default)만 가능하고 멤버변수, 클래스변수, 메서드에는 위 4개의 접근제어자 모두가 가능하다.

캡슐화

캡슐화와 접근제어자
1. 접근제어자를 사용하는 이유 : 외부로부터 데이터를 보호하기 위해서

ex)

public class Time {
	public int hour;
    public int minute;
    public int second;
}

Time t = new Time();
t.hour = 25;	// 멤버변수에 직접 접근

public class Time {
	private int hour;	// 외부에서 멤버변수에 직접 접근하지 못하도록 private으로 
    private int minute;
    private int second;
    
    public int getHour() {};	
    public int setHour(int hour) {	// 메서드를 통한 간접접근 허용
    	if(hour < 0 || hour > 23)
        	return;
            this.hour = hour;
   	}
}   

외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해

다형성

여러가지 형태를 가질 수 있는 능력
조상 타입의 참조변수로 자손 타입의 객체를 다루는 것

조상 타입의 참조변수이므로 조상 클래스에 존재하는 멤버들만 다룰 수 있다. 즉, 사용할 수 있는 멤버의 갯수가 같거나 줄어든다.

주의) 자손 타입의 참조변수로는 조상 타입의 객체를 다룰 수 없다. 이유로는 자손 타입이 다룰 수 있는 멤버들이 조상 타입의 객체보다 많아서 자손타입에는 있고 조상타입에는 없는 멤버를 사용하면 에러가 발생하기 때문이다.

참조변수의 형변환

사용할 수 있는 멤버의 갯수를 조절하는 것
조상, 자손 관계의 참조변수는 서로 형변환 가능

class Car {
	String color;
    int door;
    
    void drive() {
    	System.out.println("drive");
    }    
    void stop() {
    	System.out.println("stop");
    }
}

class FireEngine extends Car {
	void water() {
    	System.out.println("water");
    }
}

FireEngine f = new FireEngine();
Car c = (Car)f;	// 조상인 Car 타입으로 형변환 가능(생략가능)
FireEngine f2 = (FireEngine)c;	// 자손인 FireEngine타입으로 형변환 가능(생략불가)

상속관계가 아닌 클래스간의 형변환은 불가능하다.

instanceof 연산자

참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환

  1. 형변환 가능한지 확인
  2. 형변환

1의 과정에서 instanceof 연산자를 사용한다.

void doWork(Car c) {
	if(c instanceof FireEngine) {	// 형변환이 가능한지 확인
    	FireEngine fe = (Car)c;	// 형변환
        fe.water();
        ...
    }
}    

매개변수의 다형성

참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

메서드 사용 시 매개변수로 조상타입을 사용하면 오버로딩 할 필요없이 자손타입의 매개변수들을 사용가능하다.

ex)

class Product {
	int price;
    int bonusPoint;
}

class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}

class Buyer {
	int money = 1000;
    int bonusPoint = 0;
}

void buy(Tv t) {
	money -= t.price;
    bonusPoint += t.bonusPoint;
}

위 메서드를 Buyer클래스에 추가하게 된다면 우리는 buy메서드를 사용할 때, Tv클래스의 객체만 매개변수로 넣을 수 있다. Computer나 Audio, Product 객체를 넣고 싶으면 메서드를 오버로딩해야한다.

위 메서드를 다형성을 활용한 메서드로 바꾸어보자.

void buy(Product p) {
	money -= p.price;
    bonusPoint += p.bonusPoint;
}

위 메서드로 변경하면 다형성에 의해서 매개변수로 Tv, Computer, Audio. 모든 자손타입의 객체들이 들어갈 수 있다. 많은 메서드들을 사용하는 것이 아니라 하나의 메서드로 사용가능한 것이다. 이것이 다형성의 장점이다.

여러종류의 객체를 배열로 다루기

조상타입의 배열에 자손들의 객체를 담을 수 있다.

ex)

Product[] p = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();

추상클래스, 추상메서드

추상클래스 : 미완성 메서드를 가지고 있는 클래스

abstract class player {
	abstract void play(int pos);	// 추상메서드, 몸통이 없는 미완성 메서드
    abstract void stop();
}

다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가.
상속을 통해 추상 클래스를 완성시켜야 인스턴스 생성 가능.
추상클래스도 생성자가 있어야 한다.

추상메서드 : 미완성 메서드. 구현부가 없는 메서드.

꼭 필요하지만 자손마다 다르게 구현될 것이라고 예상되는 경우에 사용.

추상클래스의 작성

여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다.

추상클래스를 참조변수로 해도 다형성이 성립한다. 타입은 추상클래스이지만 실제 존재하는 객체를 다루기 때문이다.

추상화 <-> 구체화

추상화된 코드는 구체화된 코드보다 유연하다. 변경에 유리.

인터페이스

추상 메서드의 집합
구현된 것이 전혀 없는 설계도.껍데기(모든 멤버가 public)

  • 인터페이스 vs 추상클래스
    추상클래스는 생성자도 가지고 있고 일반 클래스에서 추상 메서드가 하나라도 있으면 추상클래스가 된다. 또한, iv도 가질 수 있다.
    반면, 인터페이스는 생성자x, iv x, 모든 메서드가 추상 메서드이다. 상수는 가질 수 있다.

public abstract는 인터페이스에서 생략 가능하다.

  • 인터페이스의 상속
    인터페이스의 조상은 인터페이스만 가능(Object아님)
    다중 상속이 가능(추상 클래스는 충돌해도 문제없음)

  • 인터페이스의 구현
    인터페이스에 정의된 추상 메서드를 완성하는 것
    일부만 구현하는 경우, 클래스 앞에 abstract를 붙여줘야 함

인터페이스와 다형성

인터페이스도 구현 클래스의 부모로 친다

class Fighter extends Unit implements Fightable {
	public void move(int x, int y) {}
    public void attack(Fightable f) {}
}

Unit u = new Fighter();
Fightable f = new Fighter();	// 인터페이스도 다형성 가능(단, 부모 메서드에 정의된 메서드만 사용가능)

인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
인터페이스를 메서드의 리턴타입으로 지정할 수 있다

인터페이스의 장점

두 대상(객체)간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다.
선언과 구현을 분리시킬 수 있게 한다.

ex)

class B {
	public void method() {
    	System.out.println("methodInB");
    }
}

interface I {
	public void method();
}

class B implements I {
	public void method() {
    	System.out.println("methodInB");
    }
}

만약 클래스A가 B에 의존하는 의존관계일때, 클래스 B를 C로 변경하게 된다면 A의 변경이 불가피하다. 하지만, 클래스A가 인터페이스I를 구현하는 클래스라면, 클래스 B를 C로 변경해도, A클래스는 인터페이스와의 관계만 가지고 있기 때문에 A클래스를 변경하지 않아도 된다는 장점이 있다.

개발시간을 단축할 수 있다.
변경에 유리한 유연한 설계가 가능하다.
표준화가 가능하다.
서로 관계없는 클래스들의 관계를 맺어줄 수 있다.

디폴트 메서드와 static 메서드

인터페이스에 디폴트 메서드, static 메서드 추가 가능(JDK1.8부터)
인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움

해결책 => 디폴트 메서드(default method)
디폴트 메서드는 인스턴스 메서드(인터페이스 원칙 위반)

  • 디폴트 메서드가 기존의 메서드와 충돌할 때의 해결책
  1. 여러 인터페이스의 디폴트 메서드 간의 충돌
    인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야한다.

  2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

profile
안녕하세요

0개의 댓글