자바의 정석 6장. 객체지향 프로그래밍 I

자바의 정석(남궁성) 독후감 형식의 글입니다

6장. 객체지향 프로그래밍1

1. 객체지향언어

1.2 객체지향언어

현실 세계를 프로그램의 세계에서 표현하기 위한 방법 p.230

  1. 코드의 관리가 용이하다
  2. 코드의 재사용성이 높다
  3. 신뢰성이 높은 프로그래밍을 가능하게 한다.

p.231 일단 프로그램을 기능적으로 완성한 다음 어떻게 하면 보다 객체지향적으로 코드를 개선할 수 있을지를 고민하여 점차 개선해 나가는 것이 좋다 → 리팩터링

2. 클래스와 객체

2.1 클래스와 객체의 정의와 용도
  • p.232 클래스에 대한 각종 메타포
    • 클래스:객체=설계도(청사진blue print):제품(들)
    • 클래스:객체=붕어빵틀:붕어빵(들)

p.232 인스턴스와 객체는 같은 의미지만 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖는다.

2.4 인스턴스의 생성과 사용 p.234
2.6 클래스의 또 다른 정의 p.243
  1. 변수 : 하나의 데이터를 저장할 수 있는 공간
  1. 배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
  2. 구조체 : 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
  3. 클래스 : 데이터와 함수의 결합(구조체 + 함수). 변수와 함수가 서로 유기적으로 연결되어 작업이 간단하고 명료해진다
  • 대표적인 클래스 : String

3 변수와 메서드

  • 메소드 vs 메서드
  • 멤버변수 = static변수 + 인스턴스 변수 p.246
3.2 클래스 변수와 인스턴스 변수

클래스변수를 참조할 때는 ‘클래스이름.클래스변수’의 형태로 하는 것이 좋다. 인스턴스 참조 변수를 통해서도 클래스변수를 사용할 수 있지만 이렇게 하면 클래스 변수를 인스턴스 변수로 오해하기 쉽기 때문이다. p.249

3.3 메서드 p.249

메서드를 사용하는 이유

  1. 높은 재사용성
  2. 중복된 코드의 제거
  3. 프로그램의 구조화
3.4 메서드의 선언과 구현

메서드의 선언부는 후에 변경사항이 발생하지 않도록 신중히 작성해야 한다. 메서드의 선언부를 변경하게 되면, 그 메서드가 호출되는 모든 곳도 같이 변경해야 하기 때문이다. →하지만 너무 겁먹지 말자. 우리에게는 강력한 리팩토링 기능을 제공하는 IDE가 있다

  • 메소드 이름 짓기 : 동사(목적어), 동사+한정사(목적어)
  • p.254 argument와 parameter의 차이 : argument는 넘겨주는 것이고 parameter는 받는 것이다.

“Parameter” vs “Argument”

3.6 return문 p.258
  • 메소드의 실행을 강제로 종료하는 효과

  • return문을 어떻게 쓰면 좋을까 : https://stackoverflow.com/questions/1419278/control-flow-via-return-vs-if-else

    • option1
    public ActionResult Edit(MyClass class)
    {
        if (!class.Editable)
           return null;
    
        class.Update();
        return View();
    }
    
    • option2
    public ActionResult Edit(MyClass class)
    {
        if (class.Editable)
        {
           class.Update();
           return View();
        }
        else
        {
           return null;
        }
    }
    
    • option3
    public ActionResult Edit(MyClass class)
    {
        ActionResult rv = null;
        if (class.Editable)
        {
            class.Update();
            rv = View();
        }
        return rv;
    }
    
  • p.260 매개변수의 유효성 검사 : IllegalArgumentException을 쓰자

    float divide(int x, int y) {
    	// 작업을 하기 전에 나누는 수(y)가 0인지 확인한다
    	if(y == 0) {
    		System.out.println("0으로 나눌 수 없습니다.");
    		return 0; // 매개변수가 유효하지 않으므로 메서드를 종료한다.
    	}
    	return x / (float)y;
    }
    

3.7 JVM의 메모리 구조

재귀호출에서 종료조건이 체크되지 못하는 경우 StackOverflowError 발생

3.11 클래스 메서드(static메서드)와 인스턴스 메서드

인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드(static메서드)로 정의한다.

  • 클래스 메소드의 용도를 유틸리티성 메소드로 한정하는 것이 좋다. 단순히 호출 속도를 빠르게 하기 위해 쓰는것은 오용할 위험이 있다.(p.278)
class Fee() {
	public int payment;
	public static int calculatePayment(int amount) {
		return amount + 1;
	}
}

class Client() {
	public int getFee() {
		Fee fee = new Fee();
		fee.calculatePayment(100); // fee.payment = fee.calculatePayment(100);
		System.out.println("fee=" + fee.payment);
	}
}

알아두면 좋아요!(p.282) → 하지만 이런식으로 사용할거면 클래스 메소드로 만들어야 한다. 왜냐하면…

int result = new MemberCall().instanceMethod1();
4.4 메소드 오버로딩의 장점 : chain overloaded functions(5.4에서 생성자를 이런식으로 호출하고 있음)
public int calculate(int a) {
	return calculate(a, 0);
}

public int calculate(int a, int b) {
	return calculate(a, b, 0);
}

public int calculate(int a, int b, int c) {
	// 실제 로직
}
5.4 생성자에서 다른 생성자 호출하기 - this(), this

생성자에서 다른 생성자를 호출할 때는 첫 줄에서만 가능하다.

5.5 생성자를 이용한 인스턴스의 복사
class Car {
	String color;
	String gearType;
	int door;

	// 2줄 짧음. 메소드명만으로 로직을 알 수 없음
	Car(Car c) {
		color = c.color;
		gearType = c.gearType;
		door = c.door;
	}

	// 2줄 더 길다. 메소드명만으로 로직을 알 수 있음
	public Car copy() {
		Car copied = new Car();
		copied.color = color;
		copied.gearType = gearType;
		copied.door = door;
		return copied;
	}
}

...
Car original = new Car();
...
**Car copied = new Car(original);
Car copied = original.copy();**
...

6.변수의 초기화

무조건 최대한 빨리 초기화 하기

멤버변수(클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만 지역변수의 초기화는 필수적이다

6.3 초기화 블럭(initialization block)

클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용된다. 인스턴스 초기화 블럭 : 인스턴스 변수의 복잡한 초기화에 사용된다.