서브루틴은 한가지의 일을 나타내지만 object는 데이터(instance variable)와 데이터에 대한 여러 작업으로 캡술화 할 수 있다.
표준 용어의 object는 변수들의 집합과 해당 변수들을 다루는 서브루틴들
class → static variable, subroutine object → non static variable, subroutine
class UserData {
static String name;
static int age;
}
-
static으로 선언되어 클래스의 일부이므로 한 사용자만 사용할 수 있다.
class PlayerData {
static int playerCount;
String name;
int age;
}
-
playerCount는 static 변수여서 class의 일부분이지만 name과 age는 non static 변수이기 때문에 object의 한 부분으로 사용된다.
- instance
-
클래스에서 생성된 object를 그 클래스의 instance라 한다.
object가 포함하는 변수는 instance 변수,
메소드는 instance 메소드.
NOTE: 각 객체에 instance 메소드의 코드가 복사되는 것은 아니지만 논리적으로 객체의 일부이다.
-
변수를 선언 하는것은 객체를 생성하는 것이아니다.
-
자바의 어떤 변수도 절대로 객체를 담을 수 없다. 객체에 대한 참소만 할 수 있다.
-
객체에 대한 참조는 객체가 저장되어 있는 메모리 주소.
-
-
한 객체 instance 변수를 다른 변수에 할당할 때 reference만 복사된다.
-
새로운 객체가 생성되는 것은 아님!
- Getter, Setter
-
-
read access와 write access을 제공한다.
-
멤버 변수에 직접 접근하지 못하게 함으로써 변수에 할당하는 값이 유효한 값인지 확인할 수 있다.
public void setTitle (String newTitle) {
if (newTitle == null) {
title = "{Untitled}";
}
else {
title = newTitle;
}
}
-
getter와 setter를 사용한다면 클래스를 수정하더라도 다른 클래스에 영향을 주지 않고 변경하는게 가능하다.
-
자바의 일부 기능은 getter와 setter의 네이밍 규칙에 의존하므로 네이밍 규칙을 엄격하게 준수해야 한다.
- Constructor
-
특별한 서브루틴
-
객체를 생성하는 역할이기 때문에 객체가 생성되기 이전부터 존재한다.
-
static 멤버와 비슷하지만 static으로 선언되지 않는다.
-
생성자가 expression인 이유? → 생성된 객체에 대한 reference를 반환하기 때문에
-
reference : object가 저장된 곳의 주소를 일련의 bit로 가지고 있는 것
- 컴퓨터가 생성자를 호풀하는 단계
-
-
heap 영역에서 객체를 저장할 수 있는 정도의 사용되지 않은 메모리 블록을 가져온다.
-
객체의 인스턴스 변수를 초기화 한다.
-
생성자의 문장이 실행된다.
-
객체에 대한 reference가 반환된다.
-
- dangling pointer error
-
객체에 대한 참조가 존재하지만 해당 객체를 삭제하는 것.
- memory leak
-
사용되지 않는 객체를 삭제하지 않는 것.
-
Note
|
클래스는 특정 프로그램에서 특정 작업을 수행하기 위해 작성되는 것이 아니라 특정 유형의 객체 또는 하나의 개념을 모델링 하기 위해서 만들어진다. |
Tip
|
문제에 대한 설명을 적어보자. 1. 명사는 클래스나 객체로 사용될 수 있는 후보이다. 2. 동사는 메소드의 후보이다. 3. 추가적인 분석을 통해서 더 많은 클래스와 메소드의 필요성을 발견할 수 있다. 4. 클래스 간의 유사성을 활용하기 위해 sub class를 사용할 수 있다. |
-
example
-
카드 게임에서 각 플레이어는 카드 패를 받는다. 덱은 섞이고 카드는 덱에서 한 장씩 가져와 플레이어의 패에 추가된다. 특정 게임에서는 패에서 카드를 제거하거나 새 카드를 추가할 수 있다. 게임은 플레이어가 받는 카드의 값과 무늬에 따라 승리 또는 패배한다.
-
명사 : 게임, 플레이어, 패, 카드, 덱, 값 및 무늬
-
동사 : 섞이고, 한장씩 가져온다, 패에 추가된다, 패에 카드를 제거하거나 추가한다, 게임은 승리를 판별한다.
-
-
- sub class
-
기존의 클래스에 몇 가지를 변경하거나 추가한 클래스.
상속하는 클래스의 private가 아닌 모든 인스턴스를 사용할 수 있다.
Note
|
메소드나 멤버 변수를 protected로 선언하면 해당 멤버가 클래스의 구현 부분임을 나타낸다. |
- inheritance
-
한 클래스가 다른 클래스로부터 일부 또는 전체 구조와 동작을 상속할 수 있다.
변수가 class A의 객체에 대한 reference를 가질 수 있다면, A의 sub class의 reference도 가질 수 있다.
Vehicle myVehicle = new Car();
- polymorphism
class Rectangle extends Shape {
void redraw() {
. . . // commands for drawing a rectangle
}
. . . // possibly, more methods and variables
}
class Oval extends Shape {
void redraw() {
. . . // commands for drawing an oval
}
. . . // possibly, more methods and variables
}
class RoundRect extends Shape {
void redraw() {
. . . // commands for drawing a rounded rectangle
}
. . . // possibly, more methods and variables
}
-
메소드가 실행 시간에 적용되는 객체의 실제 유형에 따라 수행되는 작업이 달라진다면 해당 메소드는 polymorphic을 가진다.
- abstract class
-
객체를 생성하는게 목적이 아닌 sub class를 만드는 목적으로 사용되는 class
- abstract method
-
sub class들이 가져야할 공통된 행위?
public abstract class Shape {
Color color; // color of shape.
void setColor(Color newColor) {
// method to change the color of the shape
color = newColor; // change value of instance variable
redraw(); // redraw shape, which will appear in new color
}
abstract void redraw();
// abstract method—must be defined in
// concrete subclasses
. . . // more instance variables and methods
} // end of class Shape
-
static nested class
-
non-static nested class (inner class)
containing class는 nested class 의 멤버가 private이라도 접근할 수 있다.
containing class에서만 사용하는 class라면 nested class로 사용하는게 바람직하다.
nested class가 containing class의 멤버 변수를 사용하는 경우 → non-static
- Local class
-
서브루틴의 local class는 해당 서브루틴의 매개변수와 지역 변수를 사용할 수 있지만 제한이 있다.
-
지역 변수나 매개변수가 final로 선언이 되어야 한다.
-
만약 final로 선언되지 않았다면 그 변수나 매개변수의 값이 서브루틴 내부에서 변하지 않아야 한다.
-
전역 변수를 사용하는것에는 문제가 없다.
-
-
FunctionalR2R[] multipliers = new FunctionalR2R[100];
for(int i = 0; i < 100; i++) {
int n = i;
multipliers[i] = z -> n * z;
}
i 는 final 변수가 아니기 때문에 직접적으로 람다 표현식에 사용하는게 불가능하다. 하지만 n은 for문 내부에서 final 변수처럼 사용되기 때문에 람다 표현식에서 사용하는게 가능하다.
FunctionalR2R[] multipliers = new FunctionalR2R[100];
for(int i = 0; i < 100; i++) {
int n = i;
multipliers[i] = new FunctionalR2R() {
public double valueAt(double x) {
return n * x;
}
};
}