코딩하는 털보

STUDY HALLE - 5주차 본문

Diary/Study Halle

STUDY HALLE - 5주차

이정인 2020. 12. 30. 18:36

STUDY HALLE

5주차 : 클래스


목표

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

학습할 것

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

과제

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

클래스 정의하기

먼저 객체지향 프로그래밍의 용어에 대해 알게된 것.

  • 객체(Object)란?

    • 사전적으로는 의사나 행위가 미치는 대상이다.

    • 프로그래밍에서는 구체적, 추상적 데이터의 단위가 된다.

    • 예) 사람, 자동차, 주문, 생산, 관리…

  • 객체 지향 프로그래밍?

    • 객체를 기반으로 하는 프로그래밍

    • 객체를 정의하고, 객체의 기능을 구현하며, 객체간의 협력을 구현한다.

  • 클래스(Class)란?

    • 객체를 코드로 구현한 것이다. (객체의 청사진)

    • 객체 지향 프로그래밍의 가장 기본적인 요소이다.

  • 멤버 변수

    • 객체가 가지는 '속성'을 변수로 표현한 것이다.
  • 메소드

    • 객체의 '기능'을 구현한 것이다.
  • 접근제어자

    • 객체의 정보 은닉에 사용되는 키워드이다.

    • public : 완전히 공개

    • private : 해당 클래스 내에서만 공개

    • protected : 상위 클래스의 private변수를 하위 클래스에서 public처럼 쓰고 싶을 때 사용

    • default(아무 접근제어자도 사용하지 않았을 때) : 같은 패키지 내에서만 공개 (package-private)

클래스 정의하기

접근제어자 class 클래스이름 {
    //구현
}
  • 하나의 java 소스 파일에 여러개의 클래스를 가질 수 있지만, public 클래스는 java 소스 파일내에 하나만 존재하며 파일의 이름과 동일해야 한다.

  • private 또는 protected 클래스는 다른 클래스 내부에만 생성할 수 있다.

학생 클래스

public class Student {  

    //학생이 가지고있는 속성을 변수로 표현 (멤버 변수, 속성)
    public int studentId; //public = 접근제어자
    public String studentName;
    public String address;
}

객체 생성하기

클래스는 객체의 청사진이며, 우리는 이 클래스를 통해서 얼마든지 여러개의 객체를 생성할 수 있다.

객체를 만들때는 'new' 키워드를 사용하며, 생성된 객체는 인스턴스라고도 한다.

(new 키워드는 배열을 생성할 때도 사용하는데, 사실 3주차 스터디에서 배열을 생성할때도 new 키워드를 사용했었다.)

객체 생성하기

new 클래스이름(argument1, argument2, ...); //argument는 클래스의 생성자에 따라 여러개거나 없을 수 있다.
  • 위처럼 new 키워드를 사용한 객체 생성 구문은 클래스의 생성자를 호출하여 메모리(힙 영역)에 객체를 생성시키고 해당 객체를 참조하는 주소값을 반환한다.

  • 일반적으로, 객체를 생성한 클래스에서 사용하기 위해 해당 클래스 타입을 가지는 참조변수에 대입하거나 초기화한다.

클래스타입 참조변수 = new 클래스이름(); //클래스 참조변수 초기화

학생 객체 생성하기

public class StudentTest { //객체를 생성하여 사용하는 건 다른 클래스인 경우가 대부분이다.

    public static void main(String[] args) {
        Student student = new Student(); //인스턴스 생성하여 참조변수 초기화

        //인스턴스의 참조 변수 사용 student
        student.studentName = "이순신";  //생성된 인스턴스(객체)의 멤버 변수를 사용할 수 있다.
        student.address = "서울";

        System.out.println(student.studentName+" "+student.address);
    }
}

참고자료 :

https://www.javatpoint.com/new-keyword-in-java


메소드 정의하기

객체가 가지는 기능을 구현하기 위해, 클래스에 구현되는 함수이다.

메소드 정의하기

    접근제어자 반환타입 메소드이름(파라미터타입 매개변수1, 파라미터타입 매개변수2, ...) {
    //work
  }
  • 메소드는 이름, 매개변수, 반환 값, 구현부로 구성된다.

  • 메소드 이름은 보통 camel notation을 사용한다. (ex) getStudentName()

  • 만약 아무 것도 반환하지 않는 메소드라면 반환타입 자리에 void 키워드를 사용한다.

  • 괄호에는 메소드가 호출될 때 받아서 처리할 데이터를 파라미터로 정의할 수 있다.

학생 클래스에 학생 정보 출력 메소드 추가하기

public class Student {  

    public int studentId;
    public String studentName;
    public String address;

    //기능을 메소드로 구현
    public void showStudentInfo() { //void:반환하는 값 없음.
        System.out.println(studentName+" "+address);
    }
}

메소드 사용하기

public class StudentTest { 

    public static void main(String[] args) {
        Student student = new Student();

        student.studentName = "이순신";
        student.address = "서울";

          //System.out.println(student.studentName+" "+student.address);
          //정의한 메소드 사용.
        student.showStudentInfo();
    }
}

생성자 정의하기

생성자(Constructor)는 객체의 생성에 사용되는 객체 요소이다.

  • new 키워드로 객체를 생성할 때 호출된다.
  • 인스턴스를 초기화(멤버변수 초기화 등) 하는 코드를 구현하는 경우가 많다.
  • 반환 값이 없고 상속되지 않는다.
  • 생성자는 클래스의 이름과 동일하다.
  • 메소드와 유사하다.

생성자 정의하기

    접근제어자 클래스이름(파라미터타입 매개변수1, 파라미터타입 매개변수2, ...) {
        //구현
    }
  • 파라미터는 객체 생성시 받을 argument를 정의하며, 구현부에서 사용할 수 있다.

디폴트 생성자

    public 클래스이름() {};
  • 아무런 생성자도 구현하지 않으면 컴파일러가 자동으로 생성해주는 생성자이다.
  • 파라미터가 없고 구현부도 없다.
  • 만약 클래스에 다른 생성자가 있는 경우 기본 생성자는 자동 생성되지 않는다.

학생 클래스 생성자 정의하기

public class Student {  

      //이름, 주소를 파라미터로 받는 생성자 정의.
    public Student(String studentName, String address) {
        this.studentName = studentName;
        this.address = address;
    }

      //디폴트 생성자가 자동으로 생성되지 않으므로 직접 정의.
    public Student(){}

    public int studentId;
    public String studentName;
    public String address;

    public void showStudentInfo() {
        System.out.println(studentName+" "+address);
    }
}

생성자를 사용해서 학생 객체 생성하기

public class StudentTest { 

    public static void main(String[] args) {
            //정의한 생성자 사용.
        Student student = new Student("이순신", "서울");      

        student.showStudentInfo();
    }
}

this 키워드

this 키워드는 객체 자신(자신의 메모리)을 가리킨다.

만약 아래와 같이 this를 반환하는 메소드를 정의했다고 가정했을 때,

public Student getSelf() { //반환 타입은 자신의 클래스 타입
        return this;
}

this를 반환하는 메소드는 객체 자신의 메모리 주소를 반환한다.

Student student = new Student("이순신", "서울");
//참조변수 s는 student와 동일한 객체를 참조한다.
Student s = student.getSelf();

//아래 3개의 출력 결과(메모리 주소)는 동일하다.
System.out.println(student);
System.out.println(student.getSelf());
System.out.println(s);

this는 특히 생성자나 메소드의 매개변수와 클래스의 멤버변수 이름이 동일할 때 사용한다.

public class Student {  

    //매개변수 studentName, address는 멤버변수 studentName, address와 이름이 같다.
    public Student(String studentName, String address) {

        //생성자 구현부에서 this는 자신(객체)를 의미한다.
        //this.studentName은 객체의 멤버변수, studentName는 파라미터로 받은 매개변수이다.
        //즉, 아래 코드는 각 멤버변수에 파라미터를 대입하는것과 같다.
        this.studentName = studentName;
        this.address = address;
    }

    public Student(){}

    public int studentId;
    public String studentName;
    public String address;

    public void showStudentInfo() {
        System.out.println(studentName+" "+address);
    }
}

this 키워드를 사용하여 생성자에서 다른 생성자를 호출 할 수 있다.

public class Student {  

    public Student(String studentName, String address) {
        this.studentName = studentName;
        this.address = address;
    }

      public Student(){
              //this로 다른 생성자를 호출할때는 그 위에 다른 로직이 있을 수 없다.
              //아마도, 객체 생성을 다음 생성자로 미루기 때문인듯 하다.
              //다른 생성자를 호출하여 값을 초기화한다.
              this("홍길동", "서울");
      }

    public int studentId;
    public String studentName;
    public String address;

    public void showStudentInfo() {
        System.out.println(studentName+" "+address);
    }
}

테스트

public class StudentTest {

    public static void main(String[] args) {
        //다른 생성자를 호출하여 값을 초기화 예상.
        Student student = new Student();

        System.out.println(student.studentName); //홍길동
        System.out.println(student.address); //서울
    }
}

int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요.

int value, Node left, right를 가지고 있어야 합니다.

BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메소드를 구현하세요.

DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.

public class BinaryTree {

    static void bfs(Node node) {
        List<Node> nodes = new ArrayList<>();
        nodes.add(node);

        while ( nodes.size() != 0 ) {
            printNodeList(nodes);
            nodes = getChildNodes(nodes);
        }

    }

    static void dfs(Node node) {
        if (node.getLeft() != null) {
            dfs(node.getLeft());
        }
        System.out.print(node);
        System.out.print(" ");
        if (node.getRight() != null) {
            System.out.print(node.getRight());
            System.out.print(" ");
        }
    }

    private static void printNodeList(List<Node> nodes) {
        for (Node node : nodes) {
            System.out.print(node);
            System.out.print(" ");
        }
    }

    private static List<Node> getChildNodes(List<Node> nodes) {
        List<Node> childNodes = new ArrayList<>();
        for (Node node : nodes) {
            if ( node.getLeft() != null ) {
                childNodes.add(node.getLeft());
            }
            if ( node.getRight() != null ) {
                childNodes.add(node.getRight());
            }
        }
        return childNodes;
    }

}

테스트

class BinaryTreeTest {

    @Test
    public void test() {
        Node node1 = new Node(5);
        Node node2 = new Node(24);
        Node node3 = new Node(30);
        Node node4 = new Node(240);
        Node node5 = new Node(360);

        //      5
        //    /   \
        //   24    30
        //  /  \
        // 240  360

        node1.setLeft(node2);
        node1.setRight(node3);
        node2.setLeft(node4);
        node2.setRight(node5);

        // bfs 1 2 3 4 5
        bfs(node1);

        System.out.println(" ");

        // dfs,중위순회 4 2 5 1 3
        dfs(node1);
    }
}
Comments