기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
코드의 재사용성을 높이고 코드의 중복을 제거-> 프로그램의 생산성과 유지보수에 큰 기여
extends
ex)
class Child extends Parent {
// ...
}
조상 클래스 : 부모(parent)클래스, 상위 (super)클래스, 기반(base)클래스
자손 클래스 : 자식 (child)클래스, 하위 (sub)클래스, 파생된 (derived) 클래스
인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.
*생성자와 초기화 블력은 상속되지 않는다. 멤버만 상속된다.
클래스내에 다른 클래스를 멤버변수로 선언하여 포함할 수 있음
class Point{
int x;
int y;
}
class Circle{
Point c = new Point();
int r;
}
상속관계 : ‘~은~이다.(is-a)’
포함관계 : ‘~은 ~을 가지고있다.(has-a)’
↔️ 다중상속 : 자바에서 지원x
자동으로 Object클래스로부터 상속받게 함
ex)
-> toString(), equals() 사용 가능
조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
접근 제어자(access modifier)와 예외(exception)는 제한된 조건 하에서만 다르게 변경할 수 있다.
단,
super
: 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수
super.변수명
Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자 this( )
또는 super( )
를 호출해야 한다. 그렇지 않으면 컴파일러가 자동적으로 super();
를 생성자의 첫 줄에 삽입한다.
*생성자가 정의되어 있는 클래스에는 컴파일러가 기본 생성자를 자동적으로 추가하지 않는다.
Point3D(int x, int y, int z) { // Point클래스를 상속 받은 클래스
super(); //Point()가 없는 경우 super(x,y)로 변경 = Point(int x, int y) 호출
this.x = x;
this.y = y;
this.z=z;
Point 클래스에 생성자 Point()
가 정의되어 있지 않으면 에러가 남
-> Point 클래스에 Point()
를 추가하거나 생성자 Point3D(int x, int y, int z)
의 첫줄에 Point(int x, int y)
를 호출하도록 변경
패키지 : 클래스의 묶음 (클래스/인터페이스 포함)
클래스들을 그룹단위로 묶어 놓은 것, 물리적으로는 하나의 디렉토리
java.lang.String
: java.lang
패키지에 속한 String
클래스
클래스 : 물리적으로 하나의 클래스 파일(.class)
*모든 클래스는 반드시 하나의 패키지에 속해야 한다.
패키지를 선언하지 않으면 자바에서 기본 제공하는 이름없는 패키지(unnamed package)에 속함
package 패키지명
컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공
(다른 패키지의 클래스를 편리하게 사용하기 위함)
java.lang
패키지는 import문으로 따로 지정하지 않아도 묵시적으로 import문이 선언되어 있음import문에서 클래스 이름 대신 *
을 사용하는 것이 하위 패키지의 클래스까지 포함하지는 x
ex)
import java.util.*;
+ import java.text.*
import java.*;
static import문을 사용하면 static멤버를 호출할 때 클래스 이름을 생략 가능
-> 특정 클래스의 static 멤버를 자주 사용할 때 편리
ex)
static java.lang.Math.random;
-> System.out.println(random());
import static java.lang.System.out;
-> out.println(random();
클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여
사용될 수 있는 곳 : 멤버변수, 메서드, 초기화 블럭
대상 | 의미 |
---|---|
멤버변수 | -모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다. -클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다. -클래스가 메모리에 로드될 때 생성된다. |
메서드 | - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다. - static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다. |
사용될 수 있는 곳 : 클래스, 메서드, 멤버변수, 지역변수
대상 | 의미 |
---|---|
클래스 | 변경/확장될 수 없는 클래스 -> final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다. |
메서드 | 변경될 수 없는 메서드 -> 오버라이딩을 통해 재정의 될 수 없다. |
멤버변수/지역변수 | 변수 앞에 final이 붙으면 값을 변경할 수 없는 상수 |
생성자를 이용한 final멤버 변수의 초기화
일반적으로 선언과 초기화를 동시에 하지만,인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있음
-> 각 인스턴스마다 final이 붙은 멤버변수가 다른 값을 갖도록 하는 것
이 가능
추상 메서드를 선언하는데 사용(메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 메서드)
대상 | 의미 |
---|---|
클래스 | 클래스 내에 추상 메서드가 선언되어 있음을 의미한다. |
메서드 | 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다. |
접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
public > protected > (default) > private
대상 | 사용가능한 접근 제어자 |
---|---|
클래스 | public, (default) |
메서드/멤버변수 | public, protected, (default), private |
지역변수 | 없음 |
접근 제어자를 사용하는 이유 : 캡슐화
인스턴스를 생성해서 반환해주는 public메서드를 제공함으로써 외부에서 이 클래스 의 인스턴스를 사용하도록 할 수 있다. 이 메서드는 public인 동시에 static이어야 한다.
class Singleton {
private Singleton() {
...
}
}
class Singleton {
private static Singleton s = new Singleton();
private Singleton(){
...
}
// 인스턴스를생성하지않고도 호출할 수있어야 하므로 static이어야한다. public static Singleton getlnstance() {
return s ;
}
}
클래스에 abstract와 final을 동시에 사용할 수 없다.
클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순되기 때문이다.
abstract메서드의 접근 제어자가 private일 수 없다.
abstract메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 private이면, 자손클래스에서 접근할 수 없기 때문이다.
메서드에 private과 final을 같이 사용할 필요는 없다.
접근 제어자가 private인 메서드는 오버라이딩될 수 없기 때문이다. 이 둘 중 하나만 사용해도 의미가 충분하다.
’여러 가지 형태를 가질 수 있는 능력’
자바 : 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함
= 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 함
(그 반대인 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.)
조상클래스 타입의 참조변수(더 작은 크기를 예상했는데) 자손클래스의 인스턴스를 참조(더 큰것을 가리키는 것은 가능)
그 반대의 경우 구현되지 않은 함수나 변수를 예상하고 접근하려 할수 있음 = 에러
서로 상속관계에 있는 클래스 사이에서만 가능
인스턴스의 실제 타입을 알아보기 위해 사용
참조변수 instanceof 타입(클래스명)
: 참조변수가 검사한 타입으로 형변환이 가능하면 true
해당 클래스를 상속받은 클래스의 instance에 대해서도 true
ex)
void doWork(Car c) {
if (c instanceof FireEngine) {
FireEngine fe = (FireEngine)c;
fe.water ();
..
} else if (c instanceof Ambulance) {
Ambulance a = (Ambulance)c;
a.siren();
}
}
매개변수를 부모클래스 타입으로 받으면 상속받은 모든 자손클래스를 매개변수로 받을 수 있음
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(Product p);
: 함수 오버라이딩 없이 Tv, Computer, Audio에 대해 모두 사용 가능
조상 타입의 참조변수 배열 -> 자소타입의 객체 참조 가능
== 미완성 설계도
추상[抽象] : 낱낱의 구체적 표상(表象)이나 개념에서 공통된 성질을 뽑아 이를 일반적인 개념으로 파악하는 정신 작용
인스턴스 생성x, 상속을 통해서 자손클래스에 의해서만 완성될 수 있다.
(=추상메서드 포함)
abstract class 클래스이름{
...
}
abstract 리턴타입 메서드이름();
자손 클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서 사용
== 기본 설계도
추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높음
-> 오직 추상메서드 + 상수만 멤버로 가짐 (일반메서드/멤버변수x)
interface 인터페이스이름 {
public static final 타입 상수이름 = 값;
public abstract 메서드이름 (매개변수목록);
}
인터페이스로부터만 상속받을 수 있음, 다중상속 가능
class 클래스이름 implements 인터페이스이름 {
} // 인터페이스에 정의된 추상메서드를 구현.
class Fighter extends Unit implements Fightable{..}
)ex)
public class TVCR extends Tv implements IVCR {
VCR vcr = new VCR();
public void play(){
vcr.play();
}
public void stop() {
vcr.stop();
}
public void reset() {
vcr.reset();
}
public int getCounter()
return vcr.getCounter();
}
public void setCounter(int c) {
vcr.setCounter(c);
}
}
인터페이스 : 구현한 클래스의 조상
-> 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있음, 형변환 가능
ex) Fightable f = (Fightable)new Fighter();
or Fightable f = new Fighter();
매개변수의 타입이나
void attack(Fightable f);
리턴 타입으로도 사용 가능
Fightable method() {
Fighter f = new Fighter();
return f;
// = return new Fighter();
}
"리턴타입이 인터페이스"
= 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환
개발시간을 단축시킬 수 있다.
인터페이스를 구현하는 클래스를 작성하는 동안 이를 사용하는 쪽도 동시에 개발할 수 있다.
표준화가 가능하다.
기본틀을 인터페이스로 작성 -> 구현
서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
인터페이스를 이용해서 클래스의 선언과 구현을 분리 -> 실제구현에 독립적인 프로그램 작성
ex)
-> SCV, Tank, Dropship 클래스 에 대해서만 repair()
를 추가하고 싶다면 인터페이스 활용
독립적인 프로그래밍이 가능하다.
인터페이스를 사용할 때의 장점
: 클래스를 사용하는 쪽이 클래스의 변경에 영향을 받지 않는다
인터페이스에 추상 메서드만 선언할 수 있다
<-> JDK1.8부터 디폴트 메서드와 static 메서드도 추가할 수 있게 됨
ex) java.util.Collection
인터페이스, 이와 관련된 static 메서드들 : Collections
라는 클래스
추상 메서드의 기본적인 구현을 제공하는 메서드
public default
+함수 (public은 생략 가능)
ex) default void newMethod(){ .. }
필요성 : 인터페이스에 메서드를 추가하면 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야 한다
-> 디폴트 메서드 추상메서드 -> 기존의 클래스드를 변경하지 않아도 됨
기존의 메서드와 이름이 중복되어 충돌하는 경우
클래스 내에 선언된 클래스
(두 클래스가 서로 긴밀한 관계에 있는 경우 사용)
장점
class Outer {
private class Instancelnner {}
protected static class Staticlnner {}
void myMethod( ) {
class Locallnner {}
}
}
접근 제어자 : abstract, final, private, protected 사용 가능
지역클래스 : 지역 클래스가 포함된 메서드에 정의된 지역변수는 final 이 붙은 지역변수만 접근 가능
(∵ 메서드가 수행을 마쳐서 지역변수가 소멸된 시 점에도,지역 클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문)
ex)
class InnerEx3 {
private int outerlv = 0;
static int outerCv = 0;
class Instancelnner {
int iiv = outerlv; // 외부 클래스의 private멤버도 접근가능하다.
int iiv2 = outerCv;
static class Staticlnner {
// 스태틱 클래스는 외부 클래스의 인스턴스멤버에 접근할 수 없다.
// int siv = outerlv;
static int scv = outerCv;
}
void myMethod() {
int lv = 0;
final int LV = 0; // JDK1.8부터 社nal 생략가능
class Locallnner {
int liv = outerlv;
int liv2 = outerCv;
// 외부 클래스의 지역변수는 final이 붙은 변수 (상수)만 접근가능하다.
// int liv3 = lv; // 에러!!!(JDK1.8부터 final 생략 가능)
int liv4 = LV; // OK
}
}
}
클래스의 선언과 객체의 생성을 동시에
= 단 한번만 사용, 오직 하나의 객체만을 생성
생성자x, 상속+인터페이스 구현 x, 둘 이상의 인터페이스 구현 x
ex)
class InnerEx6 {
Object iv = newObject(){ void method(){} }; // 익명 클래스
static Object cv = newObject(){ voidmethod(){} }; //익명 클래스
void myMethod() {
Objectlv=newObject(){ void method(){} }; // 익명 클래스
}
}
Sometimes, setup files outside of the game can be used to change certain settings. You can usually find the game's setup files in the installation directory. Check those out to see if you can make changes right there. quordle