본문 바로가기
CodeStatesBootCamp/Review

Section 1 - Unit 5 : [Java] 객체지향 프로그래밍 기초 Review

by JKROH 2023. 2. 23.
반응형
Review 에서는 학습한 내용을 다시금 기록합니다.
Unit Review는 학습한 내용 중 기존에 알고 있었지만 정확하게 이해하지 못하던 정보와 새롭게 알게된 정보를 기록합니다. 추가적인 설명을 요하는 부분은 댓글로 남겨주세요.
Section Review는 전반적인 Section을 되돌아보고 학습했던 시간과 과정, 내용을 총괄하여 기록합니다.

<<객체지향 프로그래밍 기초>>


필드와 메서드

* 필드

- 필드

  • 필드는 '클래스에 포함된 변수'로 객체의 속성을 정의할 때 사용한다.
  • 자바에서의 변수는 크게 클래스 변수, 인스턴스 변수, 지역 변수로 나뉜다.
  • 필드에는 클래스 변수와 인스턴스 변수가 포함되며 이들은 static 키워드의 유무로 구분한다
  • 정적 변수를 클래스 변수, 그렇지 않은 변수를 인스턴스 변수로 구분한다.
  • 클래스 변수는 한 클래스로부터 생성되는 모든 인스턴스들이 특정한 값을 공유해야 하는 경우에 주로 사용한다.
  • 클래스 변수는 정적 변수이기 때문에 클래스명.클래스변수명 을 통해 사용이 가능하다.
  • 필드 변수는 강제로 초기화가 이뤄진다.

* static 키워드

  • 정적 멤버는 모든 객체와 메모리를 공유한다.
  • 정적 변수는 정적 멤버임을 표시하기 위해 클래스명.멤버명 의 형태로 사용할 것을 권장한다.
  • 정적 멤버는 클래스 내부에 저장 공간을 가지고 있기 때문에 객체 생성 없이 곧바로 사용할 수 있다.
  • 정적 필드는 객체 간 공유 변수의 성질이 있다. 즉, 서로 다른 객체 인스턴스에서 각자 다르게 정적 변수의 값을 변경했다면, 해당 정적 변수의 값은 가장 마지막으로 변경된 값으로 클래스 내에 저장된다.

* 메서드 오버로딩

  • 메서드 오버로딩은 하나의 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것을 의미한다.
  • 이 때, 같은 이름의 메서드끼리 서로 다른 파라미터의 갯수나 타입을 정의해야 메서드 오버로딩이 성립된다.

생성자

* 생성자

  • 생성자는 인스턴스를 '생성'하는 메서드가 아니다. 인스턴스의 생성은 생성자 앞 new키워드가 담당한다.
  • 생성자는 인스턴스 변수의 초기 값을 parameter를 통해 설정하는 역할을 하는 메서드다. 즉, parameter를 통해 변수에 대한 의존을 주입하는 형태의 메서드다.

* this vs this()

- this()

  • this() 메서드는 자신이 속한 클래스에서 다른 생성자를 호출할 때 사용한다.
  • 클래스 내부 메서드에서 필드의 변수를 이용하거나 변경시킬때 'this.변수명'을 사용하는 것과 비슷하다.
  • this() 메서드는 생성자의 내부에서만 사용 될 수 있으며, 반드시 생성자의 첫 줄에 위치해야 한다.
  • this() 메서드는 생성자가 여러 개로 오버로딩 되었을 때 활용할 수 있다. 아래의 예시를 통해 알아보자.
public class Member {

    String name;
    int id;
    String email;
    
    public Meber(String name){
    	this.name = name;
    }
    
    public Meber(String name, int id){
    	this.name = name;
        this.id = id;
    }
    
    public Meber(String name, int id, String email){
    	this(name, id); // this() 메서드를 통해 불필요한 코드의 반복을 줄일 수 있다.
        this.email = email;
    }

내부 클래스

* 내부 클래스

  • 내부 클래스는 클래스 내부에 선언된 클래스로, 외부 클래스와 내부 클래스가 서로 연관되어 있을 때 사용한다.
  • 내부 클래스를 사용하면 다른 객체를 담는 클래스를 추가적으로 생성할 필요가 없어 코드의 복잡성을 줄이고 불필요한 클래스의 생성을 줄일 수 있으며, 캡슐화를 이루는데도 유용하다.
  • 당연하게도, 내부 클래스는 외부 클래스보다 하위 객체이다. 
  • 내부 클레스는 인스턴스 내부 클래스, 정적 내부 클래스, 지역 내부 클래스, 익명 내부 클래스로 나뉜다.
  • 익명 클래스는 이름을 가지지 않는 클래스로 단 하나의 객체만을 생성하는 일회용 클래스이다.
  • 몬스터 볼에 담길 포켓몬 객체를 만들 때, 굳이 Pokemon 클래스를 새롭게 만들어서 외부에 Pokemon이라는 객체가 있다는 사실을 알리는 것보다. MonsterBall 내부에 구현하면, 캡슐화가 더 단단해지면서 동시에 MonsterBall과 Pokemon은 원활한 상호작용이 가능할 것이다.
종류 선언 위치 사용 가능한 변수
인스턴스 내부 클래스 외부 클래스의 멤버변수 선언위치에 선언(멤버 내부 클래스) 외부 인스턴스 변수, 외부 전역 변수
정적 내부 클래스 외부 클래스의 멤버변수 선언위치에 선언(멤버 내부 클래스) 외부 전역 변수
지역 내부 클래스 외부 클래스의 메서드나 초기화 블럭 안에 선언 외부 인스턴스 변수, 외부 전역 변수
익명 내부 클래스 클래스의 선언과 객체의 생성을 동시에 하는 일회용 익명 클래스 외부 인스턴스 변수, 외부 전역 변수

 

* 멤버 내부 클래스

  • 멤버 내부 클래스는 인스턴스 내부 클래스와 정적 내부 클래스를 칭한다.

- 인스턴스 내부 클래스

  • 인스턴스 내부 클래스는 객체 내부에 멤버의 형태로 존재한다.
  • 외부 클래스의  private을 포함한 모든 접근 지정자의 멤버에 접근 가능하다.
  • 인스턴스 내부 클래스는 외부 클래스에 의존적이기 때문에 반드시 외부 클래스를 생성한 이후에 사용해야 한다. 따라서 프로그램의 실행과 동시에 메모리 공간을 할당받는 정적 멤버는 인스턴스 내부 클래스에서 선언할 수 없다.
class Box {

    private final String boxName;
    private final int size;

    private Item item;

    public Box(String boxName, int size, String itemName) {
        this.boxName = boxName;
        this.size = size;
        item = new Item(itemName);
    }

    class Item {
        String itemName;

        public Item(String itemName) {
            this.itemName = itemName;
        }

        void showBoxAndItem(){
            System.out.printf("%d크기의 %s의 %s입니다.", size, boxName, itemName); // private으로 설정한 Box 클래스의 size와 boxName에도 접근이 가능하다.
        }
    }
    public void doItemsJob(){
        item.showBoxAndItem();
    }

}


public class Main{
    public static void main(String[] args){

        Box box = new Box("상자 1호", 3, "이펙티브 자바");
        box.doItemsJob();

    }
}
더보기

 해당 코드의 main method를 실행하면 내부 클래스가 외부 클래스의 private한 멤버들에도 접근해 데이터를 읽어와 "3크기의 상자 1호의 이펙티브 자바입니다." 가 콘솔에 출력된다.

 

- 정적 내부 클래스

  • 외부 클래스의 존재와는 무관하게 정적 변수를 사용하기 위해서는 정적 내부 클래스를 구현해야한다.
  • 정적 내부 클래스를 사용하면 외부 클래스를 생성하지 않아도 내부 클래스를 사용할 수 있다.
  • 해당 기능을 응용하여 BoxFactory 객체를 Box의 정적 내부 클래스로 생성하였다. 해당 방법을 사용하면 Box의 생성자를 private하게 바꿀 수 있다.
  • 그러나 해당 방법이 효율적이며 안전한 방법인지는 모르겠다. 추후 이펙티브 자바에서 해당 부분을 학습할 예정이다.
class Box {

    private final String boxName;
    private final int size;

    private Box(String boxName, int size) {
        this.boxName = boxName;
        this.size = size;
    }

    static class BoxFactory {
        static Box makeBoxFactory(String boxName, int size) {
            return new Box(boxName, size);
        }
    }

    @Override
    public String toString() {
        return size + "크기의 " + boxName + "입니다";
    }
}

public class Main {
    public static void main(String[] args) {
        Box box = Box.BoxFactory.makeBoxFactory("상자 1호", 3);
        System.out.println(box);
    }
}
더보기

 해당 코드를 실행하면 Box 객체가 생성되고 "3크기의 상자 1호입니다" 가 출력된다.

 

* 지역 내부 클래스

  • 지역 내부 클래스는 메서드 내에서 정의되는 클래스다.
  • 메서드 내부에서만 사용가능하기 때문에 메서드 내부에서 선언하고 객체를 생성해서 사용한다.
class Box {

    String owner = "어린 왕자";

    void whatIsInBox(){
        class Item {
            String item;

            public Item(String item) {
                this.item = item;
            }

            void print(){
                System.out.println(owner + "의 상자에는 "+item+"가 들어있습니다.");
            }
        }

        Item item = new Item("코끼리");
        item.print();
    }
}

public class Main {
    public static void main(String[] args) {
        Box box = new Box();
        box.whatIsInBox();
    }
}
더보기

 위의 코드를 실행하면 "어린왕자의 상자에는 코끼리가 들어있습니다." 가 출력된다.

반응형

댓글