Practice JAVA - 클래스의 구성 멤버

최정환·2022년 12월 14일
0

Practice JAVA

목록 보기
6/10

OOP

OOP란 객체를 하나씩 조립해서 완성품을 만드는 기법이다.

클래스(설계도)를 이용해 인스턴스(객체)를 만든다.
클래스로 부터 만들어진 객체를 인스턴스라고한다.

하나의 클래스는 여러 개의 인스턴스를 만들 수 있다.

일반적으로 선언할 클래스를 파일 이름으로 파일을 생성한다.
그리고 그 하나의 파일 안에는 특이한 경우가 아닌 경우에는 하나의 클래스만을 선언하는 것을 권장한다.

// Person.java
public class Person {
	...
}

// Different.java
public class Different {
	public static void main(String[] args){
    	// Person 클래스를 이용해 인스턴스 생성
    	Person p1 = new Person();
    }
}

클래스 구성

public class ClassProperty {
	String name; // field
    ClassProperty(){...} // constructor
    void methodFn(){...} // method
}

Field(객체의 데이터가 저장되는 곳)

필드는 변수라고 부르지 않는다.
하지만 필드는 클래스 내부의 전역 변수와 같은 역할을 한다.
변수는 생성자와 메소드 내에서만 사용되고 생성자와 메소드가 종료되면 자동 소멸하지만 필드는 생성자와 메소드 전체에서 사용되며 소멸되지 않는 한 객체와 생명을 함께 한다.

Constructor(객체 생성 시 초기화 역할)

new 연사자로 호출되는 블록으로 객체 생성시 초기화를 담당한다.
클래스 이름으로 되어있고 리턴 타입이 없다.

Method(객체의 동작에 해당하는 실행 블록)

메소드를 호출하게 되면 중괄호 블록에 있는 모든 코드들이 일괄적으로 실행된다.
객체 간 데이터를 전달하는 수단이다.

생성자(Constructor)

생성자는 new 연산자로 클래스로부터 객체(인스턴스)를 생성할 때 호출되어 객체의 초기화를 담당한다.

객체 초기화란 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말한다.

new 연산자에 의해 성공적으로 실행되면 heap 영역에 객체가 생성되고 객체의 주소가 리턴된다.

기본 생성자

모든 클래스는 생성자(Constructor)가 반드시 존재하며 하나 이상 가질 수 없다.

만약 생성자 선언을 생략했다면 컴파일러는 기본 생성자를 바이트 코드에 자동 추가한다.

public Person(){
	// 생성자 무조건 하나
	Person(){...}
    pvsm(String args[]){}
}

클래스에는 하나의 생성자만 존재하지만 그 생성자를 Override할 수 있다.

public Person(){
	// 생성자 무조건 하나
	Person(){...}
    Person(String name){...}
    Person(String name, int age){...}
    pvsm(String args[]){}
}

다른 생성자 호출 this()

이렇게 override가 많아질 수록 생성자 간의 중복 코드가 발생할 수 있다.
매개 변수의 수만 달리하고 필드 초기화 내용이 비슷한 생성자가 이러한 현상이 많이 나오게 된다.

이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.

중복된 코드가 많은 생성자

Person(String name){
	this.name = name;
    this.age = 25;
    this.height = 173;
}

Person(String name, int age){
	this.name = name;
    this.age = age;
    this.height = 173;
}

Person(String name, int age, int height){
	this.name = name;
    this.age = age;
    this.height = height;
}

this를 이용한 생성자 호출

public class Person{

	String name;
    int age;
    int height;

  Person(String name){
      this(name,25,173);
  }

  Person(String name, int age){
      this(name, age, 173);
  }

  Person(String name, int age, int height){
      this.name = name;
      this.age = age;
      this.height = height;
  }

}

메소드

메소드 선언부를 메소드 시그니처라고 한다.

returntype methodname(args){
	...
}

함수와 사용하는 방법은 동일하다.

매개 변수의 개수를 모를 경우

이미 메소드의 용도가 정확히 정해져 있는 상황이 아닌 경우 매개 변수의 개수가 몇개일지 모르는 경우가 생길 수 있다.

이럴 때는 매개 변수를 배열 타입으로 선언한다.

int[] values = {1,2,3};
int sum(int[] values){};
int result = sum(values); // 1+2+3
int result = sum(new int[]{1,2,3,4,5}) // 1+2+3+4+5

int sum2(int ... values){}
int result2 = sum2(1,2,3);
int result2 = sum2(1,2,3,4,5);

메소드 Override

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것도 가능하다.

    void seat(int ... value){
        int result = 0;
        for (int i : value) {
            result += i;
        }
        System.out.println("이 차에는 몇명이 탈 수 있나요 " + result);
    }
    // method override
    void seat(String value){
        System.out.println("이 차에는 몇명이 탈 수 있나요 " + value);
    }

인스턴스 멤버와 정적 멤버

인스턴스 멤버 : 객체마다 가지고 있는 멤버

인스턴스 멤버는 인스턴스 생성 후 사용할 수 있는 필드와 메소드를 말한다.
이들은 각각 인스턴스 필드, 인스턴스 메소드라고 부른다.
인스턴스 내에 소속된 멤버기 때문에 인스턴스 없이는 사용 불가능하다.

public class Car{
	int gas;
    void setSpeed(int speed){...}
}

Car newCar = new Car();
newCar.gas = 10;
newCar.setSpeed(40);

객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언한다.

정적 멤버 : 클래스에 위치시키고 객체들이 공유하는 멤버

정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다.

정적 멤버 선언은 static 키워드를 추가한다.

public class Car{
	// 정적 필드
	static String color;
    // 정적 메소드
    static void printColor(){...}
}

객체마다 가지고 있을 필요가 없는 공용 데이터라면 정적 필드로 선언한다.

public class Calculator {
	int minus(int x, int y){return x-y;};
	static double pi = 3.14159;
    static int plus(int x, int y){return x+y;};
    
    static void Test(){
    	// error
        this.minus(1,2);
    }
}

double circle = 10*10*Calculator.pi;
int sum = Calculator.plus(2,3);

💡 정적 멤버를 사용할 때는 인스턴스 멤버를 사용할 수 없다. this를 이용해도 불가능하다.

싱글톤

전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우 사용하는 객체

싱글톤을 만들려면 클래스 외부에서 new 를 아용해 생성자를 호출할 수 없도록 막아야한다.
따라서 constructor에 private를 붙여준다.

public class Single{
	// 정적으로 인스턴스를 생성가능하게 하지만 외부에서 호출이 불가능함
	private static Single singleton = new Single();
    // 외부 호출 xx
    private Single() {}
    // 자기 자신의 인스턴스를 리턴하는 함수
    static Single getInstance(){
    	return singleton;
    }
}

// 두 변수가 가지고 있는 메모리 주소는 동일하다.
Single firstSingle = Single.getInstance();
Single secondSingle = Single.getInstance();

이러면 메소드를 이용해 생성을 하더라도 같은 메모리 주소를 가지고 있는 인스턴스가 생성된다.

final

final은 초기값이 저장되면 프로그램 실행 중에 수정할 수 없다.

초기값을 주는 방법은 두가지다.

필드 선언시 주기

생성자에서 주기

public class Me(){
	// 선언시
	final String name="Jung";
    
    // 생성자에서
    final int age;
    
    Me(int age){
    	this.age = age;
    }
}

0개의 댓글