Chapter 1: 클래스(Class)와 객체(Object)
- 클래스(Class)
- 객체(Object)
- 추상화(Abstraction)
Chapter 2: 캡슐화(Encapsulation)
- 데이터와 메소드의 결합
- 접근 가시성 제어
- 왜 캡슐화를 해야 하는가?
- 객체 데이터
- 정적 메소드 사용
Chapter 3: Java와 객체지향
- Hello, World Revisited
- 단순한 클래스 정의
- 새 객체 인스턴스화
- this 키워드
- 포함된 클래스 생성
- 포함된 클래스에 접근
Lab 7-1 클래스를 만들고 사용
Chapter 4: 객체지향 시스템 정의
- 상속(Inheritance)
- 클래스 계층구조(Hierarchy)
- 단일/다중 상속
- 다형성(Polymorphism)
- 추상 클래스(abstract class)
- 인터페이스(interface)
- Early/Late binding
Chapter 1: 클래스(Class)와 객체(Object)
클래스(Class)
일반적인 행위(Method)와 상태(Data)를 설명하는 이름이 붙여진 statement의 구조
객체(Object)
- 클래스의 인스턴스(instance)
- 객체의 3가지 특징(3요소)
- Identity(ID): 한 객체는 다른 객체와 구분될 수 있다.
- Behavior(행위): 객체는 다른 작업을 수행함. - Method를 의미.
- State(상태): 객체는 상태를 포함. - Data를 의미.
추상화(Abstraction)
- 복잡한 것을 명확(단순)하게 만드는 것.
- 어떤 것이 중요하고, 필요하고, 신뢰 가능한지에 대한 판단. (불필요한 것을 제거)
- 캡슐화는 추상화의 강력한 도구.
Chapter 2: 캡슐화(Encapsulation)
데이터와 메소드의 결합
- 데이터와 메소드를 하나의 캡슐로 결합, 캡슐 경계는 내/외부를 결정
- 캡슐화(Encapsulation)의 중요한 두 가지 관점
- 데이터와 기능을 단일 개체로 결합
- 개체의 모든 멤버(메소드, 변수 등)에 대한 접근 가시성 제어
접근 가시성 제어
- 메소드는 public, 외부에서 볼 수 있다.
- 데이터는 private, 내부에서만 볼 수 있다.
* ADT(Abstract Data Type, 추상 데이터 타입) : 데이터 표현이 완전히 비공개인 유형
왜 캡슐화를 해야 하는가?
- 캡슐화의 2가지 목적
- 사용 제어: 개발자가 의도한 방식으로만 사용할 수 있도록 설계.
- 변경의 영향 최소화: 내부 구현이 변경되어도 외부 영향은 최소화 되어야 하는데, public은 사용자도 접근할 수 있어서 사용자의 코드도 다 바꿔야한다. (나중에 코드 수정시 내가 한 변경이 다른 객체에 영향을 주지 않게 할 수 있다.)
객체 데이터
- 객체 데이터는 개별 객체에 대한 정보를 설명한다. ex) balance, owner ...
- 객체 내부에서 static 데이터를 제외한 모든 데이터 항목은 각각의 객체에 대한 정보다.
- 객체 내의 데이터는 private로 유지되며, 객체의 메소드를 통해서만 access 하는게 좋다.
정적 메소드(Static Method) 사용
- Static Method는 Static Data만 access할 수 있다.
- Static Method는 클래스에서 호출된다. 객체가 아니다.
Chapter 3: Java와 객체지향
Hello, World Revisited
- 런타임의 클래스 호출
- 클래스에 정적 main 메소드가 있으면, 컴파일러는 이를 프로그램 entry point로 만든다.
(이때, main 메소드의 시그니처는 public static void main(String[] args)와 같아야 한다. - main 함수(progrm entry point)가 없으면 일종의 라이브러리가 된다.
- 클래스에 정적 main 메소드가 있으면, 컴파일러는 이를 프로그램 entry point로 만든다.
- main이 Static Method인 이유
- Static Method는 런타임이 class의 instance를 만들 수 없다.
- 만약, main이 동적 메소드라면 런타임은 실행시에 main 메소드를 호출하기 위해 객체를 생성해야 한다.
ex) Example example = new Example(); example.main();
단순한 클래스 정의
- data와 class 모두 Class 내에 위치.
- method는 public, data는 private.
class BankAccount {
public void withDraw(int amount)
{ ... }
public void deposit(int amount)
{ ... }
private decimal balance;
private String name;
}
새 객체 인스턴스화 (객체 생성)
- Class 변수 정의는 객체를 생성하지 않음.
- new 연산자를 사용해서 객체 생성. (클래스의 객체가 메모리에 생성)
class Program {
public static void main(String[] args) {
int age = 27;
// BankAccount의 객체가 메모리에 생성되고 account(변수)가 이를 가리킴.
BankAccount account = new BankAccount();
Account.deposit(2200);
}
}
this 키워드
- 메소드를 호출하는 현재 객체, 즉 자기 자신을 참조함.
- Static Method/Data는 객체에 속하지 않는다. 따라서 this로 호출 불가
/* 객체지향 언어에서 사용하는 일반적인 용법 */
class Time {
public Time (int hour, int minite) {
this.hour = hour;
this.minite = minute;
}
}
/* this를 반환하는 것은 객체 자신을 반환한다는 뜻이다. */
class Song {
public Song setArtist(String artist) {
this.artist = artist;
return this;
}
public Song setTitle(String title) {
this.title = title;
}
}
포함된 클래스 생성
- 클래스는 클래스를 포함할 수 있다.
/* Bank 클래스에 포함된 Account 클래스 -> 다른 클래스에서 호출: Bank.Account */
class Program {
public static void main(String[] args) {
Bank.Account account = new Bank.Account();
}
}
class Bank {
… class Account { ... }
}
포함된 클래스에 접근
포함된 클래스는 public 또는 private로 선언될 수 있음
class Bank {
public class Account { ... }
private class AccountNumberCreator { ... }
}
class Program {
public static void main(String[] args) {
Bank.Account // 접근 가능
Bank.AccountNumberCreator // 접근 불가
}
}
/* NumberSetter은 private지만, Account 내에 선언되었고,
setup() 메소드는 account 메소드이기 때문에 access 가능. */
class Bank
{
public class Account {
public void setup() {
NumberSetter.set(this); // 접근 가능
balance = 0;
}
private class NumberSetter {
public static void set(Account account) {
account.number = nextNumber++;
}
private static int nextNumber = 2311;
}
private int number;
private int balance;
}
}
Lab 7-1 클래스를 만들고 사용
2024.08.27 - [코딩 문제] - [코딩 문제] 은행 계좌 코드
[코딩 문제] 은행 계좌 코드
lightningtech.tistory.com
Chapter 4: 객체지향 시스템 정의
상속(Inheritance)
- 상속은 "is a kind of" 관계를 지정.
- 상속은 클래스 사이의 관계다.
- 파생된 클래스는 존재하는 클래스에서 Specialization됨.
클래스 계층구조(Hierarchy)
- 상속과 관련된 클래스는 Class Hierarchy를 형성.
단일/다중 상속
- Single Inheritance: 하나의 기본 클래스에서 파생.
- Multiple Inheritance: 하나 or 그 이상의 클래스에서 파생.
다형성(Polymorphism)
- 기본 클래스에 선언된 메소드가 파생된 클래스에 따라 다양한 방식으로 구현될 수 있다.
- 메소드 이름은 기본 클래스에 존재.
- 메소드 구현은 파생된 클래스에 존재.
추상 클래스(abstract class)
- 직접 인스턴스 생성 X, 주로 상속을 통해 다른 클래스들이 공통으로 가져야 할 메서드나 속성 정의에 사용.
- Java에서는 abstract 키워드를 사용.
* 스타크래프트 예시
/* abstract class: Unit.java */
public abstract class Unit {
protected String name;
protected int hp;
protected int attackPower;
public Unit(String name, int hp, int attackPower) { // 생성자: 초기화 역할
this.name = name;
this.hp = hp;
this.attackPower = attackPower;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getHp() {
return this.hp;
}
public String getName() {
return this.name;
}
public int getAttackPower() {
return this.attackPower;
}
public void attack(Unit unit) {
System.out.println(this.name + "이 " + unit.name + "을 공격합니다");
unit.setHp(unit.getHp() - this.attackPower);
}
}
/* Zergling.java: Unit.java를 상속받음 */
public class Zergling extends Unit{
public Zergling(String name, int hp, int attackPower) {
super(name, hp, attackPower);
}
}
/* marine.java: Unit.java를 상속받음.
다형성: Overriding -> attack 메소드 */
public class Marine extends Unit{
public Marine(String name, int hp, int attackPower) {
super(name, hp, attackPower);
}
public void attack(Unit unit) { // Overriding
System.out.println(this.name + "이 " + unit.name + "을 원거리 공격합니다");
unit.setHp(unit.getHp() - this.attackPower);
}
}
인터페이스(interface)
- 메소드의 선언만 포함하며, 실제 구현은 포함 X.
- Super class에서 선언. Sub class에서 구현.
- interface(Super class)와 implements(Sub class) 키워드 사용
interface Drawable {
void draw(); // 메소드 시그니처만 정의
}
interface Resizable {
void resize();
}
class Shape implements Drawable, Resizable { // interface는 다중 상속 가능
@Override
public void draw() {
System.out.println("Drawing shape");
}
@Override
public void resize() {
System.out.println("Resizing shape");
}
}
Early/Late binding
- Early binding(Static binding)
- 메소드 호출이 컴파일 타임에 결정.
- 주로 Method Overloading에서 발생,
- 컴파일러는 메소드 호출 시점에 적절한 메소드를 선택(메소드 시그니처에 따라 메소드는 구분되기 때문에)
- Late binding(Dynamic binding)
- 메소드 호출이 런타임에 결정.
- 주로 Method Overriding에서 발생.
- 런타임에 메소드의 실제 구현이 호출. (프로그램 돌려봐야 알기 때문에)
2024.08.27 - [코딩 문제] - [코딩 문제] 분수 계산(사칙연산) 코드
[코딩 문제] 분수 계산(사칙연산) 코드
lightningtech.tistory.com
출처: https://github.com/gikpreet/class-programming_with_java/tree/master
GitHub - gikpreet/class-programming_with_java
Contribute to gikpreet/class-programming_with_java development by creating an account on GitHub.
github.com
'Java' 카테고리의 다른 글
[Java] Getter / Setter 메소드 (0) | 2024.08.28 |
---|---|
[Java] 08. 참조 타입 (2) | 2024.08.28 |
[Java] 06. 배열 (0) | 2024.08.25 |
[Java] 배열의 출력, 비교, 복사, 정렬 (0) | 2024.08.25 |
[Java] 05. 메소드와 파라미터* (0) | 2024.08.23 |