5주차 과제: 클래스

2020. 12. 22. 20:56백기선의 온라인 자바 스터디

반응형

- 목표

    - 자바의 Class에 대해 학습하세요.


- 학습할 것

  • 클래스 정의하는 방법
  • 객체 만드는 방법 (new 키워드 이해하기)
  • 메소드 정의하는 방법
  • 생성자 정의하는 방법
  • this 키워드 이해하기

과제 (옵션)

  • int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.
  • int value, Node left, right를 가지고 있어야 합니다.
  • BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.
  • DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.

● 클래스 정의하는 방법

 클래스란? 

- 객체를 정의해놓은 것. 또는 클래스는 '객체의 설계도 또는 틀'이라고 정의. 클래스는 객체를 생성하는데 사용.

 클래스를 정의하는 방법 

- 예를 들어 사람 객체의 클래스는 Person, 자동차 객체의 클래스는 Car라고 정해놓는다.

- 실별자 작성 규칙

  • 하나 이상의 문자로 이루어져야 한다. 예) Car, SportsCar
  • 첫 글자에는 숫자가 올 수 없다. 예) Car, 3Car(x)
  • '$', '_' 외의 특수 문자는 사용할 수 없다. 예) $Car, _Car, @Car(x), #Car(x)
  • 자바 키워드는 사용할 수 없다. 예) int(x), for(x)

- 클래스 이름을 정했다면 '클래스 이름.java'로 소스파일 생성 후 클래스를 선언한다.

public class 클래스이름 {
	//...
}

//일반적으로 소스 파일당 하나의 클래스를 선언한다. 하지만 2개 이상의 클래스 선언도 가능.
public class Car {
}

class Tire {
}

2개 이상의 클래스가 선언된 소스 파일을 컴파일 하면 바이트 코드 파일(.class)은 클래스를 선언한 개수만큼 생긴다.

결국 소스파일은 클래스 선언을 담고 있는 저장 단위일 뿐, 클래스 자체가 아니다. (위코드 컴파일 시 Car.class 와 Tire.class가 각각 생성된다.

- 클래스의 구성 멤버

public class ClassName {

    //필드 - 객체의 데이터가 저장되는 곳
    int fieldname;
    
    //생성자 - 객체 생성 시 초기화 역할 담당
    ClassName() {...}
    
    //메소드 - 객체의 동작에 해당하는 실행 블록
    void methodName() {...}
    
 }
  • 필드(Field)

    - 필드는 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳.
    - 기존 변수와는 다르게 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재한다.

  • 생성자(Constructor)

    - 생성자는 new연산자로 호출되는 특별한 중괄호 {}블록 이다. 
    - 생성자의 역할은 객체 생성 시 초기화를 담당한다. ->객체를 사용할 준비를 하는 것.
    - 클래스 이름으로 되어있으며 리턴 타입이 없다.

  • 메소드(Method)

    - 객체의 동작에 해당하는 중괄호 {}블록을 말한다.
    - 메소드는 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 생성해서 다양한 기능을 수행하기도 함.

    - 객체 간의 데이터를 전달하는 수단.

  • 접근 제어자

    public : 모든 패키지에서 해당 클래스로 접근가능
    -
    protected : 상속받은 클래스에서 접근가능
    private : 자신을 포한한 패키지에서만 해당 클래스로 접근 가능

 객체 만드는 방법(new 키워드 이해하기) 

클래스로 부터 객체를 생성하려면 new 연산자를 사용하면된다.

//new 연산자로 생성된 객체는 메모리 힙 영역에 생성된다.
new 클래스명();


//현실세계에서 물건의 위치를 모르면 물건을 사용할 수 없듯이,
//메모리 내에서 생성된 객체의 위치를 모르면 사용할 수 없다.
//new연산자는 힙 영역에 객체를 생성시킨 후 객체의 번지를 리턴한다.
//클래스로 선언된 변수에 new 연산자가 리턴한 객체의 번지를 저장하는 코드다.

클래스명 변수명;
변수명 = new 클래스명();

클래스명 변수명 = new 클래스명();

TV t; //TV클래스 타입의 참조변수 t를 선언
t = new TV();  //Tv인스턴스를 생성한 후, 생성된 TV인스턴스의 주소를 t에 저장.

클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화 라고 하며, 어떤 클래스로부터 만들어진 객체를그 클래스의 인스턴스(instance)라고 한다.

인스턴스 생성 과정.


 메소드 정의하는 방법 

- 메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말한다.

반환타입 메서드이름 (타입 변수명, 타입 변수명, ...) //반환타입과 타입변수명은 없을수 있다.
{
	// 메서드 호출시 수행될 코드
}


      ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
      
      
int add(int a, int b) {

	int result = a + b;
    
    return result;  //호출한 메서드 반환타입이 int이기 때문에 int로 반환.
    
}

- 메서드 이름은 자바 식별자 규칙에 맞게 작성한다.

  • 숫자로 시작하면 안되고, $와 _를 제외한 특수문자를 사용하지 말아야 한다.
  • 관례적으로 메소드 이름은 소문자로 작성한다.
  • 서로 다른단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫 글자는대문자로 작성한다.
  • 메소드이름은 이 메소드가 어떤 기능을 수행하는지 쉽게 알 수 있도록 기능 이름으로 지어주는 것이 좋다. 메소드 이름의 길이는 프로그램 실행과는 무관하니 너무 짧게 주지 않도록 한다.

- JVM의 메모리 구조와 메소드.

호출 스택(Call Stack) 또는 execution stack.

- 호출 스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 
- 메서드가 호출되면 호출스택에 호출된 메서드를 위한 메모리가 할당된다.
- 이 메모리는 메서드가 작업을 수행하는 동안 지역변수(매개변수 포함)들과 연산의 중간결과 등을 저장하는데 사용.
- 메서드가 작업을 마치면 할당되었던 메모리 공간은 반환되어 비워진다.
- 호출스택의 제일 위에 있는 메서드가 현재 실행중인 메서드. 아래에 있는 메서드가 바로위의 메서드를 호출한 메서드.

- 메소드 오버로딩

한 클래스 내에 같은 이름의 메서드를 여러개 정의하는 것을 '오버로딩(overloading)이라고 한다.

메소드 오버로딩의 조건은 매개변수의 타입, 개수, 순서 중 하나가 달라야 한다는 점이다.

오버라이딩 조건.

[보기 1]
int add(int a, int b) { return a+b; }
int add(int x, int y) { return x+y; }
//매개변수의 이름만 다를 뿐 매개변수의 타입이 같기 때문에 오버로딩 x.

[보기2]
int add(int a, int b) { return a+b; }
long add(int a, int b) {return (long)(a+b); }
//리턴타입만 다르고 매개변수의 타입과개수가 일치하기 때문에 오버로딩 x.

[보기3]
long add(int a, long b) { return a+b; }
long add(long a, int b) { return a+b; }
//매개변수의 순서가 다른 경우이기 때문에 오버로딩 o.

같은 일을 하지만 배개변수를 달리해야 하는 경우에, 이름은 같고 매개변수를 다르게 하여 오버로딩 구현.(장점)

 

 생성자 정의하는 방법 

생성자는 new연산자로 호출되는 중괄호{} 블록이다. 객체 생성 시 초기화를 담당하며, 모든 클래스에 반드시 하나 이상 존재한다. 클래스 내부에 선언을 생략하면 기본 생성자가 자동으로 추가된다.

-기본 생성자

  • 객체의 초기화란 필드를 초기화하거나 메소드를호출해서 객체를 사용할 준비를 하는것을 말한다.
  • 생성자를 실행하지 않고는 클래스로부터 객체를 만들 수 없다.
  • new연산자에 의해 생성자가 성공적으로 실행되면 힙 영역에 객체가 생성되고 객체의 번지가 반환된다.
  • 예를들어 Car클래스를 설계할 때 생성자를 생략하면 기본생성자가 다음과 같이 생성된다.

그렇기 때문에 클래스에 생성자를 선언하지 않아도 다음과 같이 new연산자 뒤에 기본 생성자를 호출해서 객체를 생성할 수 있다.

Car myCar = new Car();  //Car()-> 기본 생성자.

위와 같은 기본 생성자가 아닌, 객체를 다양한 값으로 초기화하기 위해서는 생성자를 명시적으로 선언해야 한다.

- 생성자 선언과 생성자 오버로딩

클래스( 매개변수선언, ...) {
	//객체의 초기화 코드
}

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

public class Car{
	//필드
    String color;
    int cc;
    
	//생성자
    public Car(String color, int cc){ //color="검정", cc=3000
    	color = color;
        cc = cc;
    }
}

public class CarExample {
	public static void main(String[] args) {
    		Car myCar = new Car("검정", 3000);
    //Car myCar = new Car(); (x) <--- 기본 생성자를 호출할 수 없음.
}

======================================================================
//생성자는 오버로딩이 가능하다. 매개변수의 타입, 개수, 순서가 다르게 선언해야 한다.
public class Car {
	Car() {...}
    Car(String model) {...}
    Car(String model, String color) {...}
    Car(String model, String color, int maxSpeed) {...}
}
//생성자가 오버로딩되어 있을 경우, new연산자로 생성자를 호출할 때 제공되는 매개값의 타입과
//수에의해 호출될 생성자가 결정된다.

생성자는 메소드와 비슷한모양을 가지고 있으나, 리턴 타입이 없고 클래스 이름과 동일하다.

위 코드의 생성자를 들여다 보면 생성자 안에 필드와 배개변수 이름이 동일하기 때문에 생성자 내부에서 해당 필드에 접근할 수 없다. 동일한 이름의 매개변수가 사용 우선순위가 높기 때문이다. 해결방법은 필드앞에 'this'를 붙인다.

 this키워드 이해하기 

  • this는객체 자신의 참조이다. 인스턴스의 주소가 저장되어 있다.
  • 'this.필드' 는 this라는 참조변수로 필드를 사용하는 것과 동일하다.
  • this를 사용하여 위 코드의 생성자를 수정해보자.
//this를 이용한 생성자
    public Car(String color, int cc){ //color="검정", cc=3000
    	this.color = color; // this.color:필드 ,, color:매개변수
        this.cc = cc;       // this.cc : 필드 ,, cc : 매개변수
    }
  • 생성자의 이름으로 클래스이름 대신 this를 사용한다.
  • 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫줄에서만 호출이 가능하다.

- 다른 생성자 호출: this()

생성자 오버로딩이 많아질경우 생성자 간의 중복된 코드가 발생할 수 있다.

생성자에서 다른 생성자를 호출할 때에는 다음과 같이 this() 코드를 사용한다.

클래스( [매개변수, ...] ) {
	this( 매개변수, ..., 값, ...); // 클래스의 다른 생성자 호출
    실행문;
}

this()는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫줄 에서만 허용한다.

 

 과제 : 트리의 구현

반응형