스터디/LiveStudy

5주차 과제: 클래스

TheWing 2020. 12. 19. 02:12

객체 지향 프로그래밍(OOP, Object-Oriented Programming)

  • 객체 지향 프로그래밍에서는 모든 객체(Object)로 취급을 한다, 이러한 객체가 바로 프로그램
  • 객체(object)란 간단히 이야기하자면 실생활에서 우리가 인식할 수 있는 사물로 설명할 수 있다.
  • 이러한 객체를 만들어 내기 위한 설계도 같은 개념을 클래스(class)라고 한다

객체지향 프로그래밍의 특징

캡상추다

캡슐화(encapsulation)

  • 보안적인 기능을 하며 내부 코드를 노출하지 않기 위한 목적

상속(inheritance)

  • 부모 클래스로부터 물려 받을 수 있다.
  • 자바에서는 확장인 extends로 알아두는것이 좋다

추상화(abstraction)

  • 생각으로 상상한 것을 실제로 옮길 수 있게, 필요한 기능을 프로그래밍 한것
  • 추상화는 모델링이다! 이렇게 생각하면 좋다

다형성(polymorphism)

  • 오버라이딩(overriding)과 오버로딩(overloading)이라고 할 수 있다.

클래스

  • 흔히 객체를 정의하는 설계도라고 한다
  • 클래스로 객체를 생성하여 사용한다
  • 변수와 메소드 등을 포함한 집합이라고 할 수 있다

예제

  • 사람 = 클래스
  • TheWing = 객체

인스턴스(instance)

  • 클래스를 사용하기 위해서는 우선 해당 클래스 타입의 객체(object)를 선언해야한다 이렇게 클래스로부터 객체를 선언하는 과정을 클래스의 인스턴스화라고 한다. 또한, 이렇게 선언된 해당 클래스 타입의 객체를 인스턴스라고 한다
  • 즉, 인스턴스란 메모리에 할당된 객체를 말한다

클래스 정의하는 방법

클래스 구조

  • 필드(field)
    • 클래스에 포함된 변수를 의미한다
    • 변수의 종류
      • 클래스 변수(static variable)
      • 인스턴스 변수(instance variable)
      • 지역 변수(local variable)
  • 메서드(method)
    • 특정 작업( 행위)을 수행 하기 위한 명령문의 집합이라고 볼 수 있다.
    • 메서드를 사용함으로써 중복되는 코드를 사용하지 않기 위함이다
  • 생성자
    • 클래스를 가지고 객체를 생성하면, 해당 객체는 메모리에 즉시 생성이된다.
public class classSample {
        int i = 0;

    public static void main(String[] args) {
        classSample sample = new classSample(); 
    }
}
  • int i = 0 는 멤버 변수이다

  • classSample() 이부분은 생성자이다

  • 아래는 메서드이다

      public static void main(String[] args) {
          classSample sample = new classSample(); 
      }

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

  • new 는 예약어이다.
  • new 로 생성자를 호출하면 객체가 생성이된다.
public class newSample {
    public static void main(String[] args) {
        newSample sample= null; // 객체 선언 
        System.out.println(sample); 
        sample = new newSample(); // newSample() 생성자를 호출하여 
                                                                    // 인스턴스 생성
        System.out.println(sample); // 참조 값 출력
    }
}
  • 결과
null
LiveStudy._5Week.newSample@7d6f77cc

메소드 정의하는 방법

main 메소드

  • Java에서 프로그램이 시작때 역할을 하는 것이다.
  • main 메소드는 필수이다. 없을 때 동작할 수 없다

리턴 타입

  • 리턴 타입은 자료형 또는 void가 올 수 있다.

return 문

  • 리턴 타입과 자료형이 일치해야한다.
  • return 을 하면 해당 메소드는 종료된다

메소드 호출

public class methodSample {
    public static void main(String[] args) {
        methodSample sample = new methodSample();
        int i = sample.methodTest(1,2); //메소드 호출
        System.out.println(i);
    }

    public int methodTest(int a , int b) {
        int sum = a + b;

        return sum; 
    }
}

결과

3

생성자 정의하는 방법

생성자(constructor)

  • 객체의 생성과 동시에 인스턴스 변수를 원하는 값으로 초기화할 수 있는 생성자라는 메소드를 제공
  • 생성자는 반환값이 없다
  • 초기화를 위한 데이터를 인수로 전달 받을 수 있다
  • 멤버 변수들을 값을 초기화 해준다.

생성자 선언

클래스이름() {...}  // 매개변수가 없는 생성자 선언
클래스이름(인수1, 인수2, 인수3) {...}  // 매개변수가 있는 생성자 선언
public class constructorSample {
    int i ;
    int a ;

    public constructorSample(int i, int a) {
        this.i = i;
        this.a = a;
    }

    public static void main(String[] args) {
        constructorSample sample = new constructorSample(1,2);
    }
}
  • 생성자를 따로 생성하지 않으면 기본 생성자로 생성이된다

this 키워드 이해하기

this와 this()

this 참조 변수

  • this 참조 변수는 인스턴스가 바로 자기 자신을 참조하는데 사용하는 변수이다.
  • this 참조 변수는 해당 인스턴스의 주소를 가리키고 있다

생성자의 예제를 보면

public class constructorSample {
    int i ;
    int a ;

    public constructorSample(int i, int a) {
        this.i = i;
        this.a = a;
    }

    public static void main(String[] args) {
        constructorSample sample = new constructorSample(1,2);
    }
}
  • 생성자의 매개변수 이름과 인스턴스 변수의 이름이 같을 경우에 this 키워드를 붙여서 구분해야한다
  • 즉, 멤버 변수 이름과 매개변수의 이름이 같고 멤버 변수에 값을 할당 할때 사용한다
  • 자바에서는 this 참조 변수를 사용하여 인스턴스 변수에 접근이 가능하다
  • 이러한 this 참조 변수를 사용할 수 있는 영역은 인스턴스 메소드뿐이며, 클래스 메소드에서는 사용할 수 없다

this() 메소드

  • this() 메소드는 생성자 내부에서만 사용이 가능하다. 같은 클래스의 다른 생성자를 호출할 때 사용한다
  • this() 메소드에 인수를 전달하면, 생성자 중에서 메소드 시그니처가 일치하는 다른 생성자를 찾아 호출해준다
    • 메소드 시그니처
      • 메소드의 이름과 메소드의 원형에 명시되는 매개변수 리스트를 가리킨다

예제

public class constructorSample {
    int i ;
    int a ;

    constructorSample(int i, int a) {
        this.i = i;
        this.a = a;
    }

    constructorSample() {
        this(1,3);
    }

    public static void main(String[] args) {
        constructorSample sample = new constructorSample(1,2);
        constructorSample sample1 = new constructorSample();
    }
}
  • this(1,3)constructorSample(int i, int a) 생성자를 호출한다

과제 (Optional)

int 값을 가지고 있는 이진 트리를 나타내는 Node 라는 클래스를 정의하세요. int value, Node left, right를 가지고 있어야 합니다.

트리 (Tree)

  • 노드로 이루어진 계층구조의 대표적 자료구조이다

트리의 특징

  • 루트 노드를 제외한 모든 노드는 단 하나의 부모 노드만 가진다

트리의 종류

이진 트리

  • 모든 노드의 자식 노드가 최대 2개인 노드들로 구성된 트리

포화 이진 트리(Full Binary Tree)

  • 모든 레벨이 full 인 이진트리

완전 이진 트리(Complete Binary Tree)

  • 모든 레벨이 꽉 찬 상태는 아니지만, 빈 틈 없이 채워진 이진 트리

Binary Search Tree(이진 탐색 트리)

  • 트리의 키에는 값이 반드시 존재하며 값들을 비교할 수 있는 집단이 존재하는 순서
  • 모든 노드의 자식 노드가 최대 2개인 트리

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

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

Node클래스

public class Node {
    private int value;
    private Node left;
    private Node right;

    public Node(Node left, Node right, int value) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    public int getValue() {
        return value;
    }

    public Node getLeft() {
        return left;
    }

    public Node getRight() {
        return right;
    }

}

BinaryTree 클래스

import java.util.*;

public class BinaryTree {

     private static Node root;
     private static BinaryTree binaryTree;

    public BinaryTree(Node root) {
        this.root = root;
    }

    public static Node getRoot() {
        return root;
    }

    public void dfs(Node root) {
        if (root == null) return;
        dfs(root.getLeft());
        System.out.print(root.getValue()+" ");
        dfs(root.getRight());
    }

    public void bfs(Node root) {
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        while (!q.isEmpty()) {
            Node node = q.poll();
            System.out.print(node.getValue()+" ");
            if (node.getLeft() != null)
                q.offer(node.getLeft());
            if (node.getRight() != null)
                q.offer(node.getRight());
        }
        System.out.println();
    }

    public static void main(String[] args) {

        Node node15 = new Node(null,null,15);
        Node node14 = new Node(null,null,14);
        Node node13 = new Node(null,null,13);
        Node node12 = new Node(null,null,12);
        Node node11 = new Node(null,null,11);
        Node node10 = new Node(null,null,10);
        Node node9 = new Node(null,null,9);
        Node node8 = new Node(null,null,8);
        Node node7 = new Node(node14,node15,7);
        Node node6 = new Node(node12,node13,6);
        Node node5 = new Node(node10,node11,5);
        Node node4= new Node(node8,node9,4);
        Node node3 = new Node(node6,node7,3);
        Node node2 = new Node(node4,node5,2);
        Node node1 = new Node(node2,node3,1);

        binaryTree = new BinaryTree(node1);
        root = binaryTree.getRoot();
        binaryTree.bfs(root);
        binaryTree.dfs(root);

    }
}

결과

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 

Reference

  • 스프링 입문을 위한 자바 객체 지향의 원리와 이해
  • 자바의신