Class

이재현·2024년 7월 25일

Java

목록 보기
7/15

Class

🩵 Class 설계

클래스는 객체의 속성들을 정의하는 설계도 같은 것으로, 필드, 생성자, 메서드로 구성되어 있다.

💙 클래스 설계의 4단계

  • 만들고자 하는 설계도를 선언 (클래스 선언)
  • 객체가 가지고 있어야 할 속성 정의 (필드 정의)
  • 객체를 생성하는 방식을 정의 (생성자 정의)
  • 객체가 가지고 있어야 할 행위를 정의 (메서드 정의)
Public class Car { // 클래스 선언
	// 필드 정의
String company; // 자동차 회사 
String model; // 자동차 모델 
String color; // 자동차 색상 
double price; // 자동차 가격 
double speed; // 자동차 속도 , km/h 
char gear; // 기어의 상태, P,R,N,D 
boolean lights; // 자동차 조명의 상태
…

// 생성자 정의, 즉 객체를 생성 시(instance 화)에 어떤 로직을 수행할지 정의
// 반환 타입은 없고, 이름은 클래스와 동일하게 설정
// 기본 생성자: 괄호 안에 아무것도 없는 생성자
Public Car() {
	// Logic, 기본생성자(생략 가능)
}


// <메서드 영역>
double gasPedal(double kmh) { // gasPedal method, input: kmh
speed = kmh; 
return speed; // output: speed
} 

double brakePedal() { // breakPedel mothod, input은 따로 없음
speed = 0; 
return speed; // output: speed
} 

char changeGear(char type) { // changeGear method, input: type (char)
    gear = type;
    return gear; // output: gear
} 
…
}



🩵 객체

객체 생성 연산자인 new를 사용하면 객체를 생성할 수 있다.
new 연산자 뒤에는 해당 클래스의 생성자 호출코드를 작성해야 한다.
형태가 Car(); 즉, 기본 생성자의 형태와 같기 때문에 new 연산자에 의해 객체가 생성되며 기본 생성자가 호출된다.

Car car1 = new Car(); // Car 클래스의 객체인 car1 인스턴스 생성

new 연산자를 통해 객체가 생성되면 해당 인스턴스 주소가 반환되기 때문에 해당 클래스의 참조형 변수를 사용하여 받아준다.
보면, 객체는 참조형 변수와 동일하게 취급되기 때문에, 배열 또는 컬렉션에도 저장하여 관리할 수 있다.




🩵 Field

필드란 객체의 데이터를 저장하는 역할을 한다.
객체의 필드는 크게 고유 데이터, 상태 데이터, 객체 데이터로 분류할 수 있다.

예를 들면 위에서 Car의 고유데이터는 회사, 모델, 색상, 가격 등이고, 상태 데이터는 속도, 기어, 라이트, 그리고 객체 데이터로는 타이어, 문, 핸들이라고 말할 수 있다.

선언한 클래스의 필드들은 기본적으로 초기값을 제공하지 않을 경우 객체 생성 시에 자동으로 기본값으로 초기화가 된다.

  • 초기값을 제공하는 방법: ‘필드타입 필드명 = 값;’의 형태로 제공할 수 있다.
    e.g. String model = “Gv80”;

필드의 값을 변경하거나 읽기 위해서는 먼저 객체가 생성되어야 한다.

Car car1 = new Car(); // 객체 생성
car1.color = “blue”; // 객체 내부 필드에 접근

이 방법은 외부에서 도트연산자를 통해 내부로 접근하는 방법이지만, 객체 내부에서도 내부 필드에 접근할 수 있다.
위의 brakePedal 메서드 부분에서 speed를 호출한 것처럼.




🩵 Method

💙 메서드 선언

메서드는 객체의 행위를 의미하며, 객체 간 협력을 위해서 사용된다.
메서드를 정의하는 방법은 {} 내부에 실행할 행위를 정의하면 된다.

double gasPedal(double kmh) { // 리턴 타입, 메서드명 (매개 변수)
speed = kmh; // 실행 코드
return speed; // output: speed
} 
  • Return Type
    Return Type이란 메서드가 실행된 후 호출을 한곳으로 값을 반환할 때, 해당 값의 타입을 의미한다.
    메서드에 리턴 타입을 선언하여 반환할 값이 있다면 반드시 return문으로 반환 값을 지정해 주어야 한다.
    만일 반환할 값이 없을 경우에는, 리턴 타입에 void를 작성해야 하고 return문은 굳이 작성하지 않아도 된다.

    • 메서드는 return문을 만나면 그대로 종료하게 되는데, void 타입일때 return;을 통해 원하는 지점에서 종료할 수도 있다.
  • 매개변수(Parameter)
    매개변수는 메서드를 호출할 때 메서드로 전달하려는 값을 받기 위해 사용되는 변수이다.

전달하려는 값이 없다면 생략할 수 있으며, 가변길이의 매개변수도 선언할 수 있다.


💙 메서드 호출

메서드 블록 내부에 작성된 코드를 실행하기 위해서는 필드 선언과 마찬가지로 객체의 생성 뒤에 사용할 수 있다.

똑같이 도트 연산자를 사용해 외부로부터 접근하는 방법이 있고, 객체 내부 메서드에서도 내부 메서드에 접근할 수 있다.

메서드의 리턴 타입을 선언하여 반환할 값이 있다면 변수를 사용해 받아줄 수 있다. 다만, 리턴 타입과 변수의 타입이 동일하거나 자동 타입 변환이 가능해야 한다.




🩵 Overloading

오버로딩은 함수가 하나의 기능만 구현하는 것이 아니라 하나의 메서드 이름으로 여러 기능을 구현하도록 하는 Java 기능이다.
즉, 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도, 매개변수의 개수, 타입, 순서가 다르다면 동일한 이름을 사용해 메서드를 정의할 수 있다.

  • 조건
    메서드 이름은 같지만, 매개 변수의 개수와 타입, 순서가 달라야 한다.
    return값 혹은 접근제어자만 다른 것은 오버로딩이 불가능하다.

  • 장점
    메서드 이름 하나로 상황에 따른 동작을 개별적으로 정의할 수 있다.
    메서드의 이름을 절약할 수 있다. (꽤 중요)




🩵 매개변수의 종류

  • 기본형 매개변수
    메서드 호출 시, 전달한 매개값으로 지정된 값을 메서드의 매개변수에 복사하여 전달한다.
    값 자체가 복사되어 넘어가기 때문에, 지정된 변수의 원본 값이 변경되지 않는다.

  • 참조형 매개변수
    메서드 호출 시, 전달할 매개값으로 지정한 값의 주소값을 매개변수에 복사하여 전달한다.
    따라서 원본의 주소를 알기에 값의 변경 또한 가능하다.

    • 매개변수뿐만 아니라 반환 타입 또한 참조형이 될 수 있다.



🩵 Instance & Class Member

Member는 필드와 메서드를 모두 합쳐서 말하는 것으로,

인스턴스 맴버란, 인스턴스 필드와 인스턴스 메서드를,

클래스 맴버란, 클래스 필드와 클래스 메서드를 말하는 것이다.

필드와 메서드의 선언 방법에 따라 나눠지게 되며, 인스턴스 맴버는 객체 생성 후에 사용할 수 있지만, 클래스 맴버는 객체 생성 없이도 사용 가능하다.


💙Instance Member

지금까지 선언한 필드와 메서드는 전부 인스턴스 맴버이다.

인스턴스 맴버는 객체를 생성해야 사용할 수 있으며, 객체의 인스턴스 필드는 각각의 인스턴스마다 고유한 값을 가질 수 있다.

인스턴스화 할 때마다 객체의 메서드를 인스턴스에 포함해야 매번 생성할 수는 없기 때문에 메서드들은 메서드 영역에 두고서 모든 인스턴스들이 공유하여 사용한다.

대신 객체 생성을 통해서만 사용할 수 있게 제한을 걸어둔 것이다.

💙Class Member

클래스는 Java의 클래스 로더에 의해서 메서드 영역에 저장되고 사용된다.

즉, 클래스 맴버란 메서드 영역의 클래스와 같은 위치에 있는 맴버들을 의미한다.

이것 때문에 클래스 맴버는 객체의 생성이 필요없이 바로 사용이 가능하게 된 것이다.

클래스 맴버는 static 키워드를 사용해서 선언할 수 있다.

일반적으로 인스턴스마다 갖고 있는 필요 없는 공용 데이터를 저장하고 있는 필드는 클래스 맴버로 선언하는 것이 좋다.

또한, 인스턴스 필드를 사용하지 않고 실행되는 메서드가 존재한다면 static 키워드를 사용하여 클래스 메서드로 선언하는 것이 좋다.
단! 클래스 맴버로 선언된 메서드는 인스턴스 맴버로 선언된 메서드들을 사용할 수 없다. (객체 생성 조건 때문에, 따라서 반대의 경우는 가능함)

클래스 멤버를 사용하려면 클래스의 이름과 함께 도트 연산자를 사용하면 된다.




🩵 지역변수

메서드 내부에 선언한 변수를 의미한다.
메서드가 실행될 때마다 독립적인 값을 저장하고 관리한다.
메서드가 종료될 때까지 유지된다.




🩵 final 필드 & 상수

Final 필드는 초기값이 저장되면 해당값을 프로그램이 실행하는 도중에는 수정할 수 없다.
Final 필드는 초기값을 지정해 주어야 한다.
필드 앞에 final 키워드를 추가해 선언할 수 있으며 사용방법은 인스턴스 필드와 동일하다.
다만, 수정이 불가능하다는 점이 다르다고 볼 수 있다.

상수는 반드시 한 개며 불변하는 값을 의미한다. 따라서 인스턴스마다 상수를 저장할 필요가 없다.
Final 앞에 static 키워드를 추가하여 모든 인스턴스가 공유할 수 있는 값이 1개이며 불변인 상수를 선언할 수 있다.
사용방법은 일반적인 클래스 필드와 동일하며, 마찬가지로 수정이 불가능하다.

  • 일반적으로 상수는 대문자로 작성하는 것이 관례이다.



🩵 생성자

생성자는 객체가 생성될 때 호출되며 객체를 초기화하는 역할을 수행한다.
생성자는 반환 타입이 없고 이름은 클래스와 동일하다.
New 연산자에 의해 객체가 생성되며 생성자가 호출된다.

  • 기본생성자
    기본 생성자는 선언 시에 괄호안에 아무것도 넣지 않는 생성자를 의미한다.
    모든 클래스는 반드시 생성자가 하나 이상 존재하며, 하나도 선언하지 않았다면 컴파일러가 기본 생성자를 바이트코드 파일에 자동으로 추가시켜준다. (하나라도 생성되어 있다면 추가해주지 않는다.)
    컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근제어자를 따른다.

  • 필드 초기화 및 생성자 오버로딩
    생성자는 객체를 초기화하는 역할을 수행한다.
    객체를 만들 때 인스턴스마다 다른 값을 가져야 할 때 생성자가 필드를 초기화 할 수 있다.
    반대로 인스턴스마다 동일한 데이터를 가지는 필드는 초기값을 대입하는 것이 좋다.

  • 주의사항!!!!
    생성자를 통해 필드 값을 초기화하고 기본 생성자를 작성하지 않았는데 기본 생성자를 호출한다면?
    한 개 이상의 생성자가 존재하기 때문에 컴파일러가 자동으로 기본 생성자를 추가해 주지 않기 때문에 기본 생성자가 존재하지 않아 오류가 발생한다.

  • 생성자 오버로딩
    생성자를 통해 필드를 초기화 할 때 오버로딩을 적용할 수 있다.
    오버로딩을 할 때, 개수, 타입, 순서가 동일한데 매개변수명만 다르게 하는 경우는 규칙에 위배되기 때문에 오류가 발생한다.




🩵 this, this()

this는 객체 즉, 인스턴스 자신을 표현하는 키워드이다.
객체 내부 생성자 및 메서드에서 객체 내부 맴버에 접근하기 위해 사용될 수 있다.
필수는 아니지만 상황에 따라 필수일 수 있으니 항상 따져봐야 한다.
객체의 메서드에서 리턴 타입이 인스턴스 자신의 클래스 타입이라면 this를 사용하여 인스턴스 자신의 주소를 반환할 수도 있다.

this()는 객체 즉, 인스턴스 자신의 생성자를 호출하는 키워드이다.
객체 내부 생성자 및 메서드에서 해당 객체의 생성자를 호출하기 위해 사용될 수 있다.
생성자를 통해 객체의 필드를 초기화할 때 중복되는 코드를 줄일 수 있다.
this() 키워드를 사용해서 다른 생성자를 호출할 때는 반드시 해당 생성자의 첫 줄에 작성되어야 한다.




🩵 접근제어자

접근제어자는 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여한다.

  • public: 접근제한이 전혀 없다.
  • protected: 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이 가능하다.
  • default: 같은 패키지 내에서만 접근이 가능하다.
  • private: 같은 클래스 내에서만 접근이 가능하다.
  • 그 외: static, final, abstract

사용가능한 접근제어자

  • 클래스: public, default
  • 메서드, 맴버변수: public, protected, default, private

접근제어자는 클래스 내부에 선언된 데이터를 보호하기 위해 사용된다.
유효한 값을 유지하도록 함부로 변경하지 못하도록 접근을 제어하는 것이 필요하다.
 캡슐화
생성자에 접근제어자를 사용함으로 인해 인스턴스의 생성을 제한할 수 있고, 일반적으로 생성자의 접근제어자는 클래스의 접근제어자와 일치한다.

💙 Getter & Setter

거의 모든 객체를 만든다고 할 때 필수적으로 들어간다.
객체의 무결성 즉, 변경이 없는 상태를 유지하기 위해 접근제어자를 사용한다. 그럴 경우에 접근 방법으로 Getter와 Setter 메서드가 있다.

Getter: 외부에서 객체의 private한 필드를 읽을 필요가 있을 때 사용한다.

private double speed; // 자동차 속도 , km/h 
private char gear = 'P'; // 기어의 상태, P,R,N,D 
private boolean lights; // 자동차 조명의 상태
…
public String getModel() { // 메서드 이름 규칙: get+필드명(첫글자는 대문자)
return model; 
} 
public String getColor() { 
return color; 
} 
public double getPrice() { 
return price; 
}

Setter: 외부에서 객체의 private한 필드를 저장 혹은 수정할 필요가 있을 때 사용한다.

private double speed; // 자동차 속도 , km/h
private char gear = 'P'; // 기어의 상태, P,R,N,D
private boolean lights; // 자동차 조명의 상태
…
public void setModel(String model) { // 메서드 이름 규칙: set+필드명(첫 글자는 대문자)
    this.model = model;
}
public void setColor(String color) {
    this.color = color;
}
public void setPrice(double price) {
    this.price = price;
}



🩵 import와 package

Package란 클래스의 일부이자, 클래스를 식별해주는 용도이다.
상위와 하위 패키지를 도트를 사용해 구분한다.

Import란 다른 패키지에 있는 클래스를 사용하기위해 명시하는 키워드이다.
클래스 이름을 생략하여 *을 사용하는 경우에는 해당 패키지 내의 모든 클래스를 사용할 수 있다.




0개의 댓글