코드스테이츠 - OOP 기초1 (클래스, 구성요소, 필드, 메서드, 생성자)

kwj1830·2022년 5월 10일
0

코드스테이츠

목록 보기
11/26
post-thumbnail

객체 지향은 일종의 방법론이다.

프로그래밍을 할 때 어떤 방식이 더 효율적이고 유지보수가 편한가?

한국에서는 Spring 프레임워크가 매우 많고, 이 Spring은 객체지향적 프레임워크다.

애초에 Java가 그렇게 설계된거 같긴함. "모든 것은 객체다"

자바스크립트 함수형 프로그램도 조금 짜봤었는데 (ㄹㅇ 쥐꼬리만큼)

객체지향의 강점은 유지보수가 쉽고 직관적이라는 것, 그리고 확장성인듯

그래서 SOLID 같은 개념도 공부해야하고 다양한 공부거리가 있다. 후...

솔직히 이건 취업을 하고 난 후에도 계속 공부해야 하는 개념이 아닐까 싶은데?


클래스

1. 구성요소

Java는 모든 것이 클래스로 이루어진다.

내 IDE 화면임. 실은 프로그래머스 알고리즘을 푼 흔적이다. 매우 쉬운 문제라 이게 뭔지 알 필욘 없음. 1레벨 개꿀쉬운문제...

왼쪽 화면은 StringPAndY 라는 이름의 클래스가 있고, 그 내부에 solution()이라는 메서드와 ramda라는 메서드가 있다.

우측 화면에는 이 클래스를 실행하기 위한 main메서드가 있다.
실은 여기선 List 다루는거 공부하기 위해서 혼자 놀고 있었음 ㅋㅋㅋ

다른 화면으로 좀 더 자세히 보자


@Data 어노테이션은 게터와 세터를 만들어준다. 물론 그거 말고도 다른 많은 것을 해준다. 여기선 게터와 세터라는 것만 있다는 것을 알자.

하여간 Item이라는 클래스에는 id, itemName, price, quantity라는 필드가 있다.

public Item() {} <-- 얘는 Item 클래스의 생성자다. 그리고 고 아래도 마찬가지
중괄호가 비어 있는 녀석은 기본 생성자고, (빈 깡통 생성)

중괄호가 복잡하게 있는 놈은 인자를 받아서 필드를 채워주는 생성자다.

생성자가 2개나 있지만, 인자를 받느냐 안받느냐에 따라 Java가 알아서 선택한다. 이걸 오버로딩이라 한다.


그리고 이놈은 메서드라고 한다. 클래스에서 어떤 특정 동작을 지시할 수 있다.

여기서는 필드값을 차례대로 콘솔에 소개하는 메서드를 작성해 둠

즉 클래스의 구성요소를 정리 하자면 다음과 같이 정리할 수 있다.

  • 클래스 이름
  • 필드
  • 생성자
  • 메서드

물론 클래스나 필드 생성시에 접근제한자나 void 같은 부분은 차후 기술하겠다.

이러한 구성요소를 바탕으로 이 Item 클래스는 Item을 양산할 수 있다.


2. 객체 생성과 활용

객체는 new라는 키워드로 생성된다.


Item item1 = new Item("아이템1", 1000, 10);
// Item 클래스로 item1이 생성되는데 얘는
// itemName = "아이템1"
// price = 1000;
// quantity = 10; 을 가진다.

new Item()에서 new는 새로운 객체를 생성해서 메모리에 넣어주겠다~ 이말이고
Item()은 클래스 구성요소의 생성자라고 생각하면 된다.

여기서 item의 메서드를 호출하는 방법은 "." 을 써서 부른다.

item1.introduce();
// itemName = 아이템1
// price = 1000
// quantity = 10

이런 식임.

물론 게터세터를 활용해서 값을 바꿔줄 수 있다.

item1.setItemName("바뀐아이템이름");
System.out.println("item1.getItemName() = " + item1.getItemName());
// item1.getItemName() = 바뀐아이템이름

3. 필드

필드는 클래스의 변수들을 뜻한다고 생각하면 편하다.

변수는 크게 3가지로 구분될 수 있다.

  • 클래스 변수
  • 인스턴스 변수
  • 지역 변수

우리가 말한 필드는 클래스, 인스턴스 변수로 볼 수 있다.

지역 변수는 for문 쓸때 자주 보는 int i 같은 녀석이 대표적인데, 그 지역에서만 사용 된다. 밖으로 뺄 수 가 없음.

    private Long id;
    private String itemName;
    private Integer price;
    private Integer quantity;
    public static Integer classVar;

여기서 private으로 선언된 모든 변수는 인스턴스 변수다.

그리고 static으로 선언된 변수는 클래스 변수로 조금 특수한 놈이다. 조금 많이 쉽게 쓰면 기본적인 변수? 라고 해야할까?

객체를 따로 생성해서 변수 값을 꺼내온 것과 다르게 public static으로 지정된 변수는 그냥 꺼내올 수 있다.

위에 import만 잘 박아두면 된다.

item1 객체 생성을 주석처리 했다.
그리고 import로 Item 클래스를 받아왔음 (맨 윗줄)
아래 있던 item1메서드들은 다 빨간색으로 오류를 띄우는데,
System.out.println("classVar = " + classVar);
은 오류 없이 잘 동작하고 있는 상태다.

일반적으로 클래스의 메서드를 사용하려고 하면 객체를 생성해야 하는데 static은 메모리 공간을 미리 공유하고 있으므로, 괜찮다.

우리가 알고리즘에서 쓰는 기초적인 메서드는 다 static이라 쇽쇽 휘갈겨 쓸 수 있는 상태임


4. 메서드(Method)

메서드, 메소드 다양한 발음을 들을 수 있을거다.

필드는 변수들을 저장하는 곳이라고 보면 쉽다.

메서드는 이 클래스가 뭔가 동작을 하는 놈이라고 보면 된다.

item으로 따지면 이름, 가격, 수량은 필드다. 메서드는 조금 동적임.

난 일종의 함수라고 생각을 하고 있었고, 크게 다르진 않다.

item1.introduce();
// itemName = 아이템1
// price = 1000
// quantity = 10

아까 위, 객체 생성에서 봤던 이놈이 메서드를 호출한거다.

introduce() 메서드를 호출하면 저런 결과를 콘솔에 출력하도록 해둔거임

public void introduce() {
	System.out.println("itemName = " + itemName);
    System.out.println("price = " + price);
    System.out.println("quantity = " + quantity);
}

이게 메서드다. 결국 Getter, Setter도 메서드다. () 괄호가 붙는다면 대충 메서드라고 보면 됨.

필드는 같은 이름의 변수를 만들 수 없지만, 메서드는 경우에 따라서 같은 이름의 메서드를 만들 수 있다.

그게 바로 오버로딩이라고 하는 용어다.

2개의 같은 이름의 메서드를 만들었음에도 인자에 따라 다른 메서드로 인식되기 때문에, 에러가 뜨지 않는다.


이렇게 호출을 한번 해보면


잘 작동되는 것도 확인할 수 있다.

Getter, Setter?

게터세터는 OOP에 중요한 부분중 하나다.
프로그래밍시에 클래스의 필드를 직접 수정할 수 없어야 한다.
필드에 따라 중요한 필드와 상시로 바뀔 수 있는 필드가 있다.

상기 item의 경우 id는 유니크한 값이어야 하고, 바뀌면 안된다.
id를 기준으로 코딩하고, DB에도 연결해야 하니까

때문에 접근제한자를 private로 선언하여 클래스 외부에서 수정하는 것을 막아둔 것임
게터 세터는 이 private으로 선언된 필드에 접근하고, 값을 수정해 줄 수 있는데,
선택적으로 메서드를 생성할 수 있기 때문에, id값에는 Getter만 (얻을 수만 있게)
게터세터를 생성해 준다면, 수정은 불가능하나 값을 얻기는 가능할 것이다.

id는 getId만 있고 set은 없다. 물론 프로그램 내부적으로 ItemRepository를 따로
운영해야 하므로, set 메서드가 필요하긴 하다. 그래도 이런 식으로 코드를 짠다면
생성 후에 수정이 불가능함을 알 수 있다. (생성자에 id값을 지정해 준다면)


5. 생성자

객체를 생성할 때 중요한 역할을 해준다.

필드값을 미리 채우고 싶을 때, 생성자에 인자를 넣어준다면 매우 편할거임

생성자를 정하지 않아도 기본적으로 깡통 생성자는 있기 때문에, 객체 생성에 문제는 없다.

문제는 깡통 생성자는 안해놨는데, 인자를 받는 생성자만 딸랑 만들어두면, 깡통 생성자가 안만들어진다는 거임

생성자는 이렇게 만든다.

/// 깡통 생성자
    public Item() {
    }

// 인자를 받는 생성자
    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }

메서드처럼 만드는데 메서드명이 클래스명인 것으로 이해하면 편하다.

그러니까 똑같은 이름을 가지고 있는데도, 다르게 작동한다. 이를 오버로딩이라고 한다.


에러가 없다.

만약 깡통 생성자가 없이, 인자를 받는 생성자만 있다면

item2는 에러가 난다. 그럴 경우 무적권 인자가 들어와야 생성이 된다.

나중에 아마 어노테이션을 다루면서 말할거 같은데, 생성자는 @Autowired 라는 어노테이션과도 연관이 깊다.

의존성 주입과 싱글톤을 생각한다면 무적권 알아야 하는 개념임

    public Item(String itemName, Integer price, Integer quantity) {
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }

이 녀석을 자세히 보면 this라는게 써 있음을 알 수 있다. this.itemName = itemName; ㅋㅋ 아니 itemName이 2개여?

this.itemName은 클래스의 필드를 지칭한다. 그리고 옆에 있는 itemName은 받아온 인자 String itemName을 말함.

즉 여기서의 this는 클래스를 뜻한다고 봐도 된다. 만약 이걸 지우고 인자 이름도 바꾸면

똑똑한 녀석이 itemName은 클래스 필드로 인식 하고, Name은 인자로 인식한다. 알아서 해준다는거임

그래도 this는 많이 쓰는 녀석이므로 참고하자.

this() 메서드
위에 설명한 this와는 다르다.
this() 메서드는 클래스가 가지고 있는 기본 메서드를 호출해준다.

    public Item() {
        System.out.println("기본 생성자를 호출했다.");
    }

	public Item(String itemName, Integer price, Integer quantity) {
        this();
        System.out.println("인자를 받는 두번째 생성자도 호출했다.");
        this.itemName = itemName;
        this.price = price;
        this.quantity = quantity;
    }

상기 코드에서 Item()은 기본 생성자다. 그리고 콘솔에 메시지를 출력하게 했다.
두번째 인자를 받는 클래스는 this()로 첫번째 생성자를 호출한 후에, 또 다른 메시지를 뱉기로 했음.

이런 식으로 보기 편하게 콘솔을 출력해보자.

this()로 인해 첫번째 생성자가 호출되고 메시지가 나옴을 알 수 있다.
this() 메서드는 생성자의 내부에서만 사용이 가능하고, 가장 첫 줄에 위치해야 한다.

profile
https://potent-grey-e01.notion.site/2d4885cad9fa4b0a8d53a784ad10cf8c <-- 알고리즘

0개의 댓글