[JAVA] 객체지향(제어자/추상화)
Categories: JAVA-Learn
📌 개인적인 공간으로 공부를 기록하고 복습하기 위해 사용하는 블로그입니다.
정확하지 않은 정보가 있을 수 있으니 참고바랍니다 :😸
[틀린 내용은 댓글로 남겨주시면 복받으실거에요]
제어자
- 제어자란
- 클래스, 변수,메서드 선언부에 사용되어 부가적인 의미를 부여
- 제어자는 크게 접근제어자와 그외의 제어자로 나뉜다.
- 하나의 대상에 여러개의 제어자를 조합해서 사용할 수 있으나 접근제어자는 단 하나만 사용할 수 있다.
- 접근제어자 : public, protected, default, private
- 그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp
- static
- static : 클래스의,공통적인
-
static이 사용될 수 있는 곳 : 멤버변수, 메서드, 초기화블럭
| 제어자 | 대상 | 의미 | | — | — | — | | static | 멤버변수 | - 모든 인스턴스에 공통적으로 사용되는 클래스변수.
- 클래스 변수는 인스턴스 생성 없이 사용 가능
-
클래스가 메모리에 로드될 때 생성됨 메서드 - 인스턴스 생성없이 호출가능 -
static메서드 내에서는 인스턴스 멤버 직접 사용 못함.
-
예제
1 2 3 4 5 6 7 8 9 10 11
class StaticTest{ static int width=200; static int height=120; static { //클래스 초기화 블럭 // static 변수의 복잡한 초기화 수행 } static int max(int a, int b){ return a > b? a: b; } }
- final
- final : 마지막의, 변경될 수 없는
-
final이 사용되는 곳 : 클래스, 메서드, 멤버변수, 지역변수
제어자 대상 의미 final 클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 됨 - 그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없음 메서드 변경 될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다. 멤버변수 변수 앞에 final이 붙으면 값을 변경할 수 없는 상수가 됨 지역변수 - 대표적인 final method 로는 Stiring 과 Math가 있음.
-
예제
1 2 3 4 5 6 7 8 9 10 11
fianl class FinalTest{ final int MAX_SIZE=10; //멤버변수 fianl void getMaxSize(){ final LV= MAX_SIZE; //지역변수 } } class Child extends FinalTest{ void getMaxSize(){} //오버라이딩 }
d. 생성자를 이용한 final 멤버변수 초기화
final이 붙은 변수는 상수이므로 보통은 선언과 초기화를 동시에 하지만, 인스턴스변수의 경우 생성자에서 초기화 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Card {
final int Number; //상수지만 선언과 함께 초기화 하지 않고
final String KIND; //생성자에서 단 한번만 초기화 할 수 있다.
static int width = 100;
static int height= 250;
Card(String kind, int num){
KIND = kind;
NUMBER = num;
}
Card(){
this("HEART",1);
}
public String toString(){
return ""+KIND+" "+NUMBER;
}
}
----
public static void maint(String[] args){
Card c = new Card("HEART", 10);
c.NUMBER = 5; //에러
System.out.printl(c.KIND);
System.out.printl(c.NUMBER);
}
- abstract
- abstract - 추상의, 미완성의
-
abstract가 사용될 수 있는 곳 : 클래스, 메서드
제어자 대상 의미 abstact 클래스 클래스 내에 추상메서드가 선언어 있음을 의미 메서드 선언부만 작성하고 구현부는 작성하지 않은 추상메서드 -
예제
1 2 3
abstract class AbstractTest{ abstract void move(); }
- 접근제어자(access modifier)
- 멤버 또는 클래스에 사용되어 , 외부로부터 접근을 제한한다.
- private : 같은 클래스 내에서만 접근 가능
- default : 같은 패키지 내에서만 접근 가능
- protected: 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능
- public : 접근 제한이 전혀 없다.
b. 접근제어자를 이용한 캡슐화
- 접근제어자를 사용하는 이유
- 외부로부터 데이터 보호하기 위해서
- 외부에는 불필요한, 내부적으로 사용되는 부분을 감추기위해
- 멤버 또는 클래스에 사용되어 , 외부로부터 접근을 제한한다.
- 생성자의 접근 제어자
- 일반적으로 생성자의 접근제어자는 클래스의 접근제어자와 일치
- 생성자에 접근제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
- ⇒ private는 연산자 new를 통해 인스턴스 생성 못함,
-
예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
final class Singleton{ //final을 붙여서 상속을 통해 확장될 수 없는 클래스임을 알려줘야함. private static Signleton s = new singleton(); // 연산자 new를 통해 인스턴스 생성 private singleton(){ //생성자, 연산자 new를 통해 인스턴스 생성못함 //... } //객체생성없이 소통하기위해 static 사용 //getInstace()에서 사용될 수 있도록 인스턴스가 미리 생성되어야 하므로 static public static Singleton genInstance(){ if(s==null){ s = new Singleton(); } return s; } } -------- class SingletonTest{ public static void main (String[] args){ // Singleton s = new Singleton(); - 에러! Singleton s1 = Singleton.getInstace() } }
-
제어자의 조합
- 메서드에 static과 abstract를 함께 사용할 수 없다.
- static 메서드는 몸통(구현부)이 있는 메서드에서만 사용할 수 있기 때문
- 클래스에 abstract와 final을 동시에 사용할 수 없다.
- 클래스에 사용되는 final 은 클래스를 확장할 수 없다는 의미이고 , abstract는 상속을 통해서 완성되어야 한다는 의미로 서로 모순
- abstract 메서드의 접근제어자가 private일 수 없다.
- abstract메서드는 자손클래스에서 구현해주어야 하는데 접근제어자가 private이면 자손클래스에 접근할 수 없기 때문
- 메서드에 private 와 final을 같이 사용할 필요 없음
- 접근제어자가 private인 메서드는 오버라이딩 될 수 없기 때문
- 둘중 하나만 써도 의미가 충분
- 메서드에 static과 abstract를 함께 사용할 수 없다.
다형성
- 다형성
- 하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것. 즉, 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것
- 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다
- 참조변수의 형변환
- 서로 상속관계에 있는 타입간의 형변환만 가능
- 자손에서 조상타입 up-casting : 형변환 생략가능
- 조상에서 자손타입 down-casting : 생략불가
- instanceof 연산자
- 이항연산자/피연산자는 참조형변수와 타입 /연산결과 true or false
- 다형성을 통해 조상타입의 instance로 자손타입의 instance를 가르킬 수 있어서
- 참조변수의 타입과 참조변수가 가르키는 instance의 타입이 항상 같지 않음
- instanceof 연산자로 어떤 타입인지 확인가능
- 그러나 실제 인스턴스 값을 알려준다기보다 형변환이 가능한지를 알려줌
- 참조변수와 인스턴스변수의 연결(이해가 잘안감…..)
- 멤버변수의 중복정의 : 참조변수의 타입에 따라 연결되는 멤버변수 달라짐 - 참조변수 타입에 영향
- 메서드 중복정의 : 실제 인스턴스 타입에 정의된 메서드 호출
- 매개변수의 다형성
- 참조형 매개변수는 메서드 호출시 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있음
- 매개변수를 참조변수로 넘겨주거나
- new 연산자로 객체 생성 후 넘겨줄 수 있음
추상클래스
- 추상클래스란
- 클래스가 설계도라면 추상클래스는 미완성 설계도
- 추상 메서드 포함하고 있는 클래스(이게 다른 클래스와의 차이점 - 생성자, 멤버변수,메서드 모두 가지고 있음)
-
추상메서드: 선언부만 있고 body는 없는 메서드
1 2 3 4 5 6 7 8 9 10 11 12
abstract class Player{ int currentPos; Player(){ currentPos =0 ; } abstract void play(int pos); //추상메서드 (선언부만 있고 몸통 x) abstract void stop(); //추상메서드 void play(){ play(currentPos); //추상메서드 사용가능) } ... }
-
- 일반메서드가 추상메서드 호출가능 (호출할때는 선언부만 있으면 되므로)
- 완성된 설계도가 아니므로 인스턴스 생성 불가능
- 다른 클래스 작성시 도움을 줄 목적으로 작성됨
- 추상메서드란
- 선언부만 있고 바디가없는 메서드
-
주석을 통해 어떤 기능을 수행할 목적으로 작성했는지 설명
1 2 3 4
abstract 리턴타입 메서드이름(); ex) /*지정된 위치 (pos)에서 재생을 시작하는 기능이 수행되도록 작성한다.*/ abstract void play(int pos);
c. 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용
d. 추상클래스를 상속받는 자손클래스에서 추상메서드의 구현부를 완성해야함
1 2 3 4 5 6 7 8 9 10 11 12 13 14
abstract class Player{ ... abstract void play(int pos); //추상메서드 abstract void stop(); //추상메서드 ... } class AudioPlayer extends Player{ void play (int pos){/*내용 생략*/} void stop() {/*내용 생략*/} } abstract class AbstractPlayer extends Player{ void play(int pos) {/*내용 생략*/} }
- 추상 클래스 작성
- 여러 클래스에 공통적으로 사용될수 있는 추상클래스를 바로 작성
-
기존의 공통 부분을 뽑아서 추상클래스를 만듬.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class Marine{ //보명 int x, y; //현재 위치 void move(int x, int y){/*지정된 위치로 이동*/} void stop() {/*현재 위치에 정지*/} void stimPack() {/*스팀팩을 사용*/} } class Tank{ //탱크 int x, y; //현재 위치 void move(int x, int y){/*지정된 위치로 이동*/} void stop() {/*현재 위치에 정지*/} void changeMode() {/*공격모드로 변환*/} } class Dropship{ //수송선 int x, y; //현재 위치 void move(int x, int y){/*지정된 위치로 이동*/} void stop() {/*현재 위치에 정지*/} void load() {/*선택한 대상을 태운다*/} void unload() {/*선택한 대상을 내린다*/} }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
abstract class Unit{ int x, y; abstarct void move(int x, int y); void stop(){/* 현재 위치에 정지*/} } class Marine extends Unit { //보병 void move(int x, int y){/*지정된 위치로 이동*/} void stimPack() {/*스팀팩을 사용*/} } class Tank extends Unit { //탱크 void move(int x, int y){/*지정된 위치로 이동*/} void changeMode() {/*공격모드로 변환*/} } class Dropship extends Unit { //탱크 void move(int x, int y){/*지정된 위치로 이동*/} void load() {/*선택한 대상을 태운다*/} void unload() {/*선택한 대상을 내린다*/} }
1 2 3 4 5 6 7 8 9 10
Unit[] group = new Unit[4]; group[0] = new MARINE(); group[1] = new Tank(); group[2] = new Marine(); group[3] = new Dropship(); for (int i=0; i<group.length;i++){ group[i].move(100,200); //추상메서드가 호출되는 것이 아니라 //각 자손들에 실제로 구현된 move(int x, y)가 호출됨 }
인터페이스
- 인터페이스란
- 일종의 추상 클래스, 추상클래스보다 추상화정도가 높음
- 구현된 것이 없는 기본 설계도
- 추상메서드와 상수만을 멤버로 가질 수 있음
- 인스턴스 생성할 수 없고 클래스 작성에 도움을 줄 목적으로 사용
- 미리 정해진 규칙에 맞게 구현하도록 표준 제시
- 인터페이스
-
class 대신 interface를 사용한다는 것 외에 클래스작성과 동일
1 2 3 4
interface 인터페이스이름{ public static final 타입 상수이름 = 값; public abstract 메서드이름(매개변수목록); }
-
하지만 구성요소(멤버)는 추상메서드와 상수만 가능
- 모든 멤버변수는 public static final이어야 하며 생략은 가능
- 모든 메서드는 public abstract이어야 하며 생략 가능.
1 2 3 4 5 6 7 8 9
interface PlayingCard{ public static final int SPADE=4; (public static) final int DIAMOND=3; (public) static (final) int Heart =2; (public static final)int CLOVER = 1; public abstract String getCardNumber(); (public abstract)String getCardKind(); }
-
- 인터페이스의 상속
-
인터페이스도 클래스 처럼 상속이 가능(클래스와 달리 다중상속 허용)
1 2 3 4 5 6 7 8 9 10
interface Movalbe{ /*지정된 위치(x,y)로 이동하는 기능의 메서드*/ void move (int x, int y); } interface Attackable{ /*지정된 대상(u)을 공격하는 기능의 메서드*/ void attack(Unit u); } interface Fightable extends Movable,Attackable{}
-
인터페이스는 Object와 같은 최고 조상이 없다.
-
- 인터페이스의 구현
- 인터페이스 구현한다는 것은 클래스를 상속받는것과 같다.
-
다만 extends 대신 implements를 사용
1 2 3
class 클래스이름 implements 인터페이스이름{ //인터페이스에 정의된 추상메서드를 구현해야함 }
-
인터페이스에 정의된 추상 메서드를 완성해야함.
1 2 3 4 5 6 7 8
class Fighter implments Fightable{ public void move(){//내용생략} public void attack(){//내용생략} } interface Fightable{ void move(int x,int y); void attack(unit u); }
1 2 3 4
abstract class Fighter implements Fightable{ public void move(){ //내용생략 }
-
상속과 구현이 동시에 가능
1 2 3 4
class Fighter extends Unit implements Fightable{ public void move (int x, int y){//내용생략} public void attack(Unit u){//내용생략} }
- 인터페이스를 이용한 다형성
-
인터페이스 타입의 변수로 인터페이스를 구현한 클래스의 인스턴스 참조가능
1 2 3 4 5 6 7 8
class Fighter extends Unit implements Fightable{ public void move (int x, int y){//내용생략} public void attack(Unit u){//내용생략} } ----------------------- Fighter f = new Fighter(); Fightable f = new Fighter();
-
인터페이스를 메서드의 매개변수 타입으로 지정가능
1 2 3
void attack(Fightable f){//Fightable 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 받는 메서드 //... }
-
인터페이스를 메서드의 리턴타입으로 지정가능
1 2 3 4
Fightable method(){ //Fightable 인터페이스를 구현한 클래스의 인스턴스반환 //.. return new Fighter(); }
-
- 인터페이스의 장점
- 개발시간단축
- 인터페이스 작성 > 프로그램 작성가능
- 메서드 호출쪽에서는 선언부만 알면 되기 때문
- 다른 클래스에서는 인터페이스 구현하는 클래스를 작성하여 양쪽 동시 개발 진행 가능
- 표준화 가능
- 프로젝트 사용되는 기본 틀을 인터페이스로 작성
- 개발자들에게 인터페이스를 구현하여 작성하도록 함
- 일관되고 정형화된 프로그램 개발 가능
- 서로 관계없는 클래스들에게 관계맺어 줄 수 있음
- 서로 상속관계에 있지않고 아무관계 없는 클래스에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어줄 수 있음.
- 독립적인 프로그래밍 가능
- 클래스의 선언과 구현을 분리 시킬 수 있어 독립적인 프로그램 작성가능
- 클래스 간의 직접적인 관계를 인터페이스를 이용하여 간접적인 관계로 변경하면 관련된 클래스에 영향을 미치지 않는 독립적 프로그래밍 가능
- 개발시간단축
-
인터페이스 장점 - 예제
- 디폴트메서드
- 인터페이스에서 디폴트메서드, static메서드를 추가 기능할 수있게 바뀜
- 클래스와 달리 인터페이스에서 새로운 메서드(추상메서드)를 추가하기 어려움
- 이러한 문제점 해결위해 디폴트메서드 고안
- 디폴트메서드는 인터페이스에 추가된 일반메서드(인터페이스 원칙 위반)
1 2 3 4
interface MyInterface{ void method(); void newMethod();//추상메서드 }
1 2 3 4
interface MyInterface{ void method(); default void newMethod(){} }
e. 디폴트 메서드가 기존의 메서드와 충돌하는 경우 아래와 같이 해결
1) 여러 인터페이스의 디폴트 메서드간의 충돌
- 인터페이스를 구현한 클래스에서 디폴트메서드를 오버라이딩 해야한다.
2) 디폴트메서드와 조상클래스의 메서드간의 충돌
- 조상클래스의 메서드가 상속되고, 디폴트메서드는 무시된다.
내부클래스(inner class)
- 내부클래스란?
- 클래스 안에 선언된 클래스
- 특정 클래스 내에서만 주로 사용되는 클래스를 내부클래스로 선언
- GUI 어플리케이션(ATW,Swing)의 이벤트 처리에 주로 사용된다.
- 내부클래스의 장점
- 내부클래스에서 외부클래스의 멤버들에게 쉽게 접근가능
- 코드 복잡성 줄일 수 있음(캡슐화)
- 내부클래스의 장점
- 내부클래스의 종류는 변수의 선언위치에 따른 종류와 동일
- 유효범위와 성질도 변수와 유사하므로 비교해보면 이해하기 쉽다.
내부클래스 특징 인스턴스 클래스 외부 클래스의 멤버변수 선언위치에 선언하며 외부클래스의 인스턴스 멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언 스태틱 클래스 외부클래스의 멤버변수 위치에 선언, 외부클래스의 static멤버 처럼 다루어진다.
주로 외부클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언지역클래스 외부클래스의 메서드나초기화 블럭안에선언, 선언된 영역 내부에서만 사용 가능 익명클래스 클래스 선언과 객체의 생성을 동시에 하는 이름없는 클래스
참고자료 - 자바의 정석
Leave a comment