객체지향 프로그래밍 기본

Moom2n·2024년 2월 27일
0

Java

목록 보기
7/26

클래스와 객체

- 클래스란?

데이터와 기능을 모두 포함하는 데이터 구조

- 객체란?

클래스의 인스턴스

  • 객체의 세 가지 특징:
    identity(ID): 한 객체는 다른 객체와 구분될 수 있음
    Behavior(행위): 객체는 작업을 수행함
    State(상태): 객체는 상태를 포함함

- 추상화란?

대상에 대해 맥락에서 필요한 것에 대한 최소한의 형태가 남을 때까지 불필요한 것을 제거하는 전략

잘 수행된 소프트웨어 추상화는 복잡한 것을 단순하게 만듭니다. 잘된 추상화는 클래스에서 불필요한 것들을 노출하지 않습니다. 필수적이지 않은 것을 숨기면 외부에서 클래스의 불필요한 부분을 보거나 그 상태 또는 행위에 종속되지 않습니다.


캡슐화

- 데이터와 메소드의 결합

- 접근 가시성 제어

변수를 숨기고, 동작만 정의한다. 클라이언트는 동일한 방법만 계속 사용하면 된다.
접근제한자 : default, public, private, protected

- 왜 캡슐화를 해야하는가?

메소드를 통해서만 접근 가능하도록 변경 허용
private 데이터 타입이 변경되어도 객체 사용에 영향을 미치지 않음

- 객체 데이터

객체 내의 데이터는 private으로 유지되며 객체의 메소드를 통해서만 액세스 할 수 있도록 하는 것이 좋습니다. 이 캡슐화는 객체가 효과적으로 추상화되어 동작한다는 것을 의미하기도 합니다.

- 정적 데이터 사용

정적 메소드(Static Method)는 정적 데이터에만 액세스 할 수 있음
정적 메소드는 클래스에서 호출됨. 객체가 아님
정적 데이터를 캡슐화 하기 위해서는 정적 메소드를 사용해야 합니다.


Java 와 객체지향

- Hello, World revisited

만약 main이 동적 메소드라면, 런타임은 실행시에 main 메소드를 호출하기 위해 객체를 생성해야 합니다.

class Example {
    void main() {}
}

이것이 뜻하는 바는, main이 동적 메소드라면 런타임은 실행을 위해 다음 코드를 실행해야 합니다.

Example example = new Example();
example.main();

- 단순한 클래스 정의

class BankAccount {
    	public void withDraw(int amount)
	{ ... }
	public void deposit(int amount)
	{ ... }
	private decimal balance;
	private String name;
}

만약 클래스 멤버를 선언할 때 접근 제한자를 쓰지 않으면 기본적으로 default 로 설정됩니다. default 는 가시성이 클래스로 제한되는 접근 제한자로, 같은 패키지 내에 있는 클래스에서는 액세스 할 수 있습니다.

- 새 객체 인스턴스화

new 연산자를 사용해서 객체 생성

class Program {
    public static void main(String[] args) {
        int age = 27;
        BankAccount account = new BankAccount();
        Account.deposit(2200);
    }
}

- this 키워드

this 키워드는 메소드/필드가 존재하는 객체 인스턴스를 참조함. 암시적으로 개체 메소드를 호출하는 객체, 즉 객체 그 자신을 참조합니다.

class Time {
    public Time (int hour, int minite) {
        this.hour = hour;
        this.minite = minute;
    }
}

호출 체인 가능. 결국 객체는 1개만 생성된다.

class Song {
    public Song setArtist(String artist) {
        this.artist = artist;
        return this;
    }
    public Song setTitle(String title) {
        this.title = title;
    }
}

- 포함된 클래스 생성

class Program {
	public static void main(String[] args) {
		Bank.Account account = new Bank.Account();
	}
}

class Bank {class Account { ... }
}

class 는 interface, enum 등 다른 종류의 타입들을 클래스에 포함할 수 있습니다. 위의 코드에서, Account 클래스는 Bank 클래스 내부에 있습니다. Account 클래스의 전체 이름은 Bank.Account 입니다. 이 이름은 Bank 클래스의 외부에서 Account 클래스에 액세스 하고자 할 때 반드시 지켜져야 합니다.

- 포함된 클래스에 접근

class Bank {
    public class Account { ... }
    private class AccountNumberCreator { ... }
}

class Program {
    public static void main(String[] args) {
        Bank.Account			// 접근 가능
        Bank.AccountNumberCreator	// 접근 불가
    }
}

데이터 및 메소드를 public 또는 private 으로 선언하여 액세스 범위를 조절할 수 있듯이, 포함된 클래스 역시 같은 방법으로 액세스 가능성을 제어합니다.


객체지향 시스템 정의

어떠한 동작이나 계산에 관련된 틀을 만들어, 그 틀끼리 상호작용하는 것이 객체지향이다.

- 상속

상속은 "is a kind of" 관계를 지정

성인 남자와 여자, 여자 아이가 있는 그림을 객체지향적으로 생각한다면, ManWoman 클래스가 있고, Woman 클래스의 인스턴스가 두 개, Man 클래스의 인스턴스가 하나 있는 것입니다. 이 예에서는 클래스간의 상속 관계가 없습니다. 상속관계를 꼭 만들어야 한다면 ManWoman 두 클래스가 공유하는 행위와 속성들을 가지는 Person 클래스를 생성하고 Person 클래스가 Man, Woman 두 클래스의 슈퍼 클래스가 되는 것입니다. Man, WomanPerson 에서 전문화되어 각각의 Person 클래스의 동작과 속성에서 추가된 동작과 속성을 가지도록 모델링 되어야 합니다.

- 클래스 계층구조

상속과 관련된 클래스는 클래스 계층 구조를 형성

한 클래스의 서브 클래스는 그 자신이 다른 클래스의 슈퍼 클래스가 될 수 있습니다. 그림에서 StringMusician 클래스는 Musician 클래스에서 파생된 서브 클래스이지만 그 자체로 추가 파생된 ViolinPlayer 클래스의 슈퍼 클래스입니다. 상속으로 관련된 클래스 그룹은 클래스 계층구조(Class Hierarchy)로 알려진 구조를 형성합니다. 계층 구조에서 위로 올라갈수록 일반적인 개념(일반화)을 나타내며 아래로 내려가면 보다 전문화된 개념(전문화)을 나타냅니다.

- 단일/다중 상속

  • 단일 상속(Single Inheritance): 하나의 기본 클래스에서 파생됨

  • 다중 상속(Multiple Inheritance): 하나 또는 그 이상의 클래스에서 파생됨

Java 에서는 다중상속을 허용하지 않는다.

- 다형성

  • 메소드 이름은 기본 클래스에 존재
  • 메소드 구현은 파생된 클래스에 존재 => 메소드 오버라이딩

- 추상 클래스(Abstract Class)

public abstract class Musician { }

- 인터페이스(Interface)

추상 클래스(abstract class)와 인터페이스(Interface)는 인스턴스화 할 수 없다는 점에서 비슷합니다.
차이점은 인터페이스는 타입의 정의를 위해 사용되고, 추상 클래스는 타입의 행위(Behavior)를 위해 사용된다는 점입니다.
추상 클래스와 다르게 추상 메소드만 가지고 있다.
초기의 인터페이스는 구현을 어떠한 종류의 구현을 포함하는 것을 허용하지 않았습니다. 추상 클래스는 멤버를 포함할 수 있습니다. 인터페이스는 operation(메소드 이름)만 포함하여 서브 타입에게 기능의 이름만 상속하고 구현을 강제합니다. 추상 클래스는 operation을 상속하지만 클래스의 멤버와 구현이 있는 메소드 역시 상속합니다. 인터페이스는 추상 클래스보다 훨씬 추상적입니다.

- 이른/늦은 바인딩(Early/Late Binding)

  • 이른 바인딩 : 일반적인 메소드 호출은 컴파일시에 지정됨
  • 늦은 바인딩 : 다형적 메소드 호출은 런타임시에 지정됨
    Unit marine = new Marine();

늦은 바인딩을 사용하면 파생된 클래스(서브클래스)를 기본 클래스로 대체할 수 있습니다. 인터페이스를 통해 operation을 호출할 수 있으며 런타임에 파생된 클래스에서 해당 메소드가 올바르게 호출됩니다. 즉, 인터페이스를 구현하는 모든 파생된 클래스는 인터페이스 타입을 대체하는 역할을 할 수 있습니다.


0개의 댓글

관련 채용 정보