The Art of Computer Programing
객체(Object)
- 클래스의 인스턴스
- 객체의 세 가지 특징:
- Identity: 한 객체는 다른 객체들과 구분될 수 있음
- Behavior(행동): 객체는 작업을 수행함
- State(상태): 객체는 상태를 포함함
추상화(Abstraction)
- 추상화는 불필요한 것을 선택하고 제거하는 것
- 어떤 것이 중요하고 어떤 것이 중요하지 않는 지에 대한 판단
- 어떤 것이 중요한지에 대해 초점을 맞추고 판단
- 어떤 것이 신뢰할 수 없고 필요 없는지에 대한 판단
- 캡슐화는 추상화의 강력한 도구
데이터와 메소드의 결합
1
2
3
4
5
6
7
8
9
public class BankAccount {
private int balance;
public void deposit(int money){
this.balance+= money;
}
public void withdraw(int money){
this.balance-= money;
}
}
- 데이터와 메소드를 하나의 캡슐로 결합
- 캡슐 경계는 내부와 외부를 설정
메소드 deposit, withdraw 와 balance 는 결합되어 있다.
접근 가시성 제어
- 메소드는 public, 외부에서 볼 수 있음
- 데이터는 private, 내부에서만 볼 수 있음
외부에서 접근한다고 할때 public으로 선언되어 있는 deposit,withdraw 는 접근 가능하지만 private으로 선언되어 있는 balance를 직접 참조하지는 못한다.
왜 캡슐화를 해야 하는가?
- 제어 허용
- 메소드를 통해서만 접근 가능하도록
balance는 메소드가 아니면 접근이 불가능하다.
- 변경 허용
- private 데이터 타입이 변경되어도 객체 사용에 영향을 미치지 않음
객체 데이터
- 객체 데이터는 개별 객체에 대한 정보를 설명
- 각 은행 계좌 객체는 각 객체의 잔고를 가지고 있음
- 만약 잔고가 같다면 우연
1
2
3
4
5
6
public class Test{
public static void main(String[] args) {
BankAccount bankAccount1 = new BankAccount();
BankAccount bankAccount2 = new BankAccount();
}
}
bankAccount1 과 bankAccount2 는 개별적으로 정보를 가지고 있다.
정적 데이터(Static Data) 사용
- 정적 데이터는 클래스에서 인스턴스화 된 모든 객체를 위한 정보를 저으이
- 은행 계좌의 모든 이자율은 같은 것이 좋음
- 만약 이자율을 각각 계좌가 가지고 있다면?
1
2
3
4
5
6
7
8
9
10
11
public class BankAccount {
private int balance;
static private int interest = 7;
static private String name = new String("name");//static 선언 확인용
public void deposit(int money){
this.balance+= money;
}
public void withdraw(){
//...
}
}
이자율 같은 경우 모든 계좌에 동일하다. 그렇기 때문에 static으로 선언해서 객체 수준에서 관리해서 이자율 변경과 메모리 사용량이 커지기 때문에 클래스 수준에서 이자율을 선언한다.
1
2
3
4
5
6
7
8
9
10
class Program{
public static void main(String[] args) {
BankAccount account1 = new BankAccount();
BankAccount account2 = new BankAccount();
if (account1.getName() == account2.getName()) {
System.out.println("equals!");
}
}
}
static으로 선언 되어있는 name을 선언할 경우 참조값이 서로 일치하기 때문에 equals가 뜨는 것을 알수있다. 만약 static이 아닐경우 아무것도 출력이 되지 않는다.
정적 메소드(Static Method) 사용
- 정적 메소드는 정적 데이터에만 엑세스 할 수 있음
- 정적 메소드는 클래스에서 호출됨. 객체가 아님
1
2
3
4
5
6
7
8
9
10
11
12
public class BankAccount {
private int balance;
static int interest(){
return 7;
}
public void deposit(int money){
this.balance+= money;
}
public void withdraw(){
//...
}
}
위와 같이 메소드를 통해 하여도 가능하다.
단순한 클래스 정의
- 데이터와 메소드 모두 클래스 내에 위치
- 메소드는 public, 데이터는 private
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BankAccount {
private int balance;
private String name;
public static int interest;
public int deposit(int amount){
this.balance+= amount;
return balance;
}
public void withdraw(int amount){
this.balance-= amount;
}
}
class Program{
public static void main(String[] args) {
BankAccount account = new BankAccount();
int deposit = account.deposit(10000);
System.out.println(deposit);
account.withdraw(1000);
//전역 변수 호출 방법
int interest = BankAccount.interest;
}
}
위에서 했던 예제를 정리하면 이렇게 활용할 수 있다.
새 객체 인스턴스화
- 클래스 변수 정의는 객체를 생성하지 않음
- new 연산자를 사용해서 객체 생성
this 키워드
- this 키워드는 메소드/필드가 존재하는 객체 인스턴스를 참조함.
- 다른 범위의 식별자가 충돌할 때 유용함.
상속
- 상속은 “is a kind of” 관계를 지정
- 상속은 클래스 사이의 관계
- 파생된 클래스는 존재하는 클래스에서 전문화됨
유닛 - 날수 없는 유닛 - 날수 있는 유닛 - 무기를 가지고 있는 유닛 boolean이 아닌 메서드로 처리하기 나는지 무기를 가지고 있는지.
클래스 계층구조
- 상송과 관련된 클래스는 클래스 계층 구조를 형성
단일/다중 상속
- 단일 상속 하나의 기본 클래스에서 파생됨
- 다중 상속 하나 또는 그 이상의 클래스에서 파생됨
다형성
- 메소드 이름은 기본 클래스에 존재
- 메소드 구현은 파생된 클래스에 존재
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface Musician{
void TuneYourInstrument();
}
class Violin implements Musician{
@Override
public void TuneYourInstrument() {
System.out.println("Violin");
}
}
class Guitar implements Musician{
@Override
public void TuneYourInstrument() {
System.out.println("Guitar");
}
}
위와 같이 메소드 이름은 기본 클래스에 구현은 파생된 클래스에 한다.
추상 클래스
- 파생되는 클래스의 기본 클래스가 되기 위해서만 존재
- 이런 종류의 클래스 인스턴스를 만드는 것은 의미가 없음
- 이런 클래스를 추상 클래스라고 부름
1
2
3
4
5
6
7
8
9
public abstract class Musician {
String music(){
return "music";
}
}
class Guitar extends Musician{
}
class Violin extends Musician{
}
위처럼 추상클래스에 선언된 내용은 파생되는 클래스는 music을 호출하여 사용할 수 있다.
인터페이스
- 인터페이스는 구현이 없는 operation의 이름만 포함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface Musician {
String music();
}
class Guitar implements Musician {
@Override
public String music() {
return "Guitar";
}
}
class Violin implements Musician{
@Override
public String music() {
return "Violin";
}
}
위처럼 구현이 없는 operation만 구현하고 실제 구현은 파생된 클래스에서 한다.
이른/늦은 바인딩
- 일반적인 메소드 호출은 컴파일시에 지정됨
- 다형적 메소드 호출은 런타임시에 지정됨