231017 TIL

SEULBI LEE·2023년 10월 17일
2

TIL

목록 보기
4/25

사소하지만 내 시간을 잡아먹은 내용

오늘은 everything이다.


자바 문법종합반 3주차

강의에서 기억하고 싶은 단어들

개념 무작정 받아적기

필드 접근 방법
객체를 생성하여 도트 연산자 사용. (외부 접근)
객체 내부 메서드에서 접근. (내부 접근)

메서드 선언
리턴 타입 메서드명 (매개변수,...){
실행할 코드 작성 ( 리턴 타입이 보이드가 아니라면 반드시 리턴이 있어야 함)
}

가변길이의 매개변수
viod carSpeeds(double ... speeds){} : ... : 매개값 개수 상관 없이 ,를 이용해 전달 가능. 실행할 코드에 개수 상관 없이 실행할 수 있도록 for문 등의 반복문 작성 필요

메서드 접근 방법
객체를 생성하여 도트 연산자 사용. 또한 메서드가 매개변수를 가지고 있다면 호출할 때 매개변수의 순서와 타입에 맞게 값 넣어줘야 함 (외부 접근)
메서드 내부에서 호출 (내부 접근)

메서드 오버로딩
메서드의 이름이 같고, 매개 변수의 개수, 타입, 순서가 달라야 합니다. (또는)
응답값만 다른 것은 오버로딩을 할 수 없습니다.
접근제어자만 다른 것도 오버로딩을 할 수 없습니다.
오버로딩은 매개변수의 차이로만 구현할 수 있습니다.
-> 메서드의 이름을 절약할 수 있습니다. 메서드 이름 하나로 상황에 따른 동작을 개별로 정의할 수 있습니다.

기본형 & 참조형 매개변수
-매개변수의 타입이 기본형일 때는 값 자체가 복사되어 넘어가기 때문에 매개값으로 지정된 변수의 원본 값이 변경되지 않습니다.
-매개변수를 참조형으로 선언하면 값이 저장된 곳의 원본 주소를 알 수 있기 떄문에 값을 읽어오는 것도 물론 값을 변경할 수 있습니다.

멤버 = 필드 + 메서드
클래스 멤버?
필드와 메서드는 선언하는 방법에 따라서 인스턴스 멤버와 클래스 멤버로 구분할 수 있습니다. 인스턴스 멤버는 객체 생성 후에 사용할 수 있고 클래스 멤버는 객체 생성 없이도 사용할 수 있습니다.

통상적으로 사용했던 메서드는 모두 클래스 멤버였습니다.
지금까지 학습하면서 선언한 필드와 메서드는 전부 인스턴스 멤버였습니다.
인스턴스 멤버는 생성과 사용을 분리해서 생각하자. (저장 공간의 문제. 공유영역 존재)

클래스는 java 클래스 로더에 의해 메서드 영역에 저장되고 사용됩니다.
객체의 생성 필요 없이 바로 사용이 가능합니다.
클래스 멤버란 메서드 영역의 클래스와 같은 위치에 고정적으로 위치하고 있는 멤버를 의미합니다.
필드와 메서드를 클래스 멤버로 만들기 위해서는 static 키워드를 이용하면 됩니다.

final 필드와 상수
final 필드 : 프로그램이 실행하는 도중에는 절대로 수정할 수 없습니다.
반드시 초기값을 지정해야 합니다.
상수 : 값은 한 개이며 불변의 값입니다. 관례적으로 전체 문자를 대문자로 적습니다.

생성자
객체가 생성될 때 호출되며 객체를 초기화해주는 역할을 수행합니다.
기본 생성자
기본 생선자는 선언할 떄 ()안에 아무 것도 넣지 않는 생성자를 의미합니다.
반면 단 하나라도 생성자가 선언되어있다면 컴파일러는 기본 생성자를 추가하지 않습니다.
컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근 제어자를 따릅니다.

생성자는 객체를 초기화하는 역할을 수행합니다.

this와 this()
this는 객체, 즉 인스턴스 자신을 표현하는 키워드입니다.
매개변수 명과 객체의 필드명이 동일할 경우 오류가 발생하지는 않지만 생성자 블록 내부에서 해당 변수들을 객체의 필드가 아닌 가장 가까운 매개변수명을 가리키게 됨으로 자기 자신에게 값을 대입하는 상황이 되어버립니다.

또한 this는 인스턴스 자신을 뜻하기 떄문에 객체의 매서드에서 리턴 타입이 인스턴스 자신의 클래스 타입이라면 this를 사용하여 인스턴스 자신의 주소를 반환할 수도 있습니다.

this()를 이용하면 코드의 중복을 제거할 수 있습니다.
this 로직을 쓸 때는 위에 어떤 다른 로직도 있으면 안 됩니다.

제어자는 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여해 줍니다.
그 외 제어자 : static, final, abstract
접근 제어자 : 멤버 또는 클래스에 사용, 외부에서 접근하지 못하도록 합니다. 클래스, 멤버 변수, 메서드, 생성자에 사용되고, 지정되어 있지 않다면 default입니다.
public(접근 제한이 전혀 없습니다.), protected(같은 패키지 내에서, 다른 패키지의 자손 클래스에 접근이 가능합니다.), default(같은 패키지 내에서만 접근이 가능합니다.), private(같은 클래스 내에서만 접근이 가능합니다.)
클래스 : public, default
메서드, 멤버 변수 : 접근 제어자 모두
지역변수 : 사용 불가
접근제어자를 이용한 캡슐화
클래스 내부에 선언된 데이터를 보호하기 위해서 사용합니다.
생성자의 접근 제어자는 클래스의 접근제어자와 일치합니다.
Getter와 Setter
객체의 무결성, 즉 변경이 없는 상태를 유지하기 위해 접근 제어자를 사용합니다. 그렇다면 우리는 어떻게 객체의 private 필드를 읽어오거나 저장할 수 있을까요? Getter와 Setter를 이용해 이를 해결할 수 있습니다.

외부의 객체의 private한 필드를 읽을 필요가 있을 때 Getter 메서드를 사용합니다.
Getter
private 필드의 값을 읽어 가져옵니다.
메서드 이름의 규칙은 get + 필드명(첫 글자 대문자)입니다.
인스턴스 메서드 호출과 벙법은 동일합니다.
Setter
외부에서 객체의 private한 필드를 저장/수정할 필요가 있을 때 Setter 메서드를 사용합니다.
getter와 똑같은 이름 규칙 및 호출 규칙을 가지고 있습니다.

제어자의 조합
사용 가능한 제어자
클래스 : public, default, final, abstract
메서드 : public, protected, default, private, final, abstract, static
멤버 변수 : public, protected, default, private, final, static
지역 변수 : final
제어자 사용 시 주의사항
메서드에 static과 abstact를 함께 사용할 수 없다.
클래스에 abstract와 final을 동시에 사용할 수 없다.
abstract 메서드의 접근 제어자가 private일 수 없다.
메서드에 private와 final을 같이 사용할 필요는 없다.

상속
부모 클래스의 필드와 메서드를 자식클래스에게 물려줄 수 있습니다.
적은 양의 코드로 새로운 클래스를 작성할 수도 있고 공통적인 코드를 관리하여 코드의 추가와 변경이 쉬워질 수도 있습니다.
이러한 특성때문에 상속을 사용하면 코드의 중복이 제거되고 재사용성이 크게 증가하여 생산성과 유지보수성에 매우 유리해집니다.

클래스 간 상속은 extends 키워드를 사용하여 정의할 수 있습니다.
상속의 개념은 확장으로 이해하면 됩니다.
1. 부모 클래스에 새로운 필드와 메서드가 추가되면 자식 클래스는 이를 상속받아 사용할 수 있다.
2. 자식 클래스에 새로운 필드와 메서드가 추가되어도 부모 클래스는 어떠한 영향도 받지 않는다.
3. 따라서 자식 클래스의 멤버 개수는 부모 클래스보다 항상 같거나 많다.

클래스간의 관계
상속 관계 is - a
포함 관계 has - a

단일 상속과 다중상속
자바는 다중 상속을 허락하지 않습니다.
클래스 간의 관계가 복잡해지는 문제가 생기기 때문입니다.
자식클래스는 서로 다른 부모 클래스들의 같은 이름의 멤버를 구분할 수 없습니다.

final 클래스와 final 메서드

부모 클래스에서 final 키워드를 지정하면 그 요소는 자식 클래스가 상속할 수 없는 클래스가 됩니다.
상속 = overriding. 기본적으로 내려받아 변경할 수 있음.

Object 클래스의 메서드 (최상위!)
Obeject clone() : 객체의 복제본을 생성하여 반환함.
boolean equals(Object object) : 해당 객체와 전달받은 객체가 같은지 여부를 반환
Class getClass() : 해당 객체의 클래스 타입을 반환함
int hashCode() : 자바에서 객체를 식별하는 정수값인 해시 코드를 반환함
String toString() : 해당 객체의 정보를 문자열로 반환함. & Object 클래스에서는 클래스 이름 @해쉬코드값 리턴함.

오버라이딩
부모 클래스로부터 상속받은 메서드의 내용을 재정의하는 것을 오버라이딩이라고 합니다.
1. 선언부가 부모 클래스의 메서드와 일치해야 합니다.
2. 접근 제어자를 부모클래스의 메서드보다 좁은 범위로 변경할 수 없습니다.
3. 예외는 부모 클래스의 메서드보다 많이 선언할 수 없습니다.

super와 super()
super는 부모 클래스의 멤버를 참조할 수 있는 키워드입니다.

다형성
자동 타입 변환
부모 타입 면수 = 자식 타입 객체;

강제 타입 변환
자식 타입 변수 = (자식 타입) 부모타입객체;
자동 형변환이 완료된 것만 돌아감.

다형성이란?
여러가지 형태를 가질 수 있는 능력

instance of
어디 클래스에 속해있는지! boolean 타입으로 응답함.
자식 객체를 부모 타입으로 자동 형변환하였어도, 클래스의 이름을 확인하는 것이기 때문에 instance of 자식 클래스 하여도 true 나옴.

추상 클래스
미완성된 설계도입니다.
abstract 키워드를 사용하여 추상 클래스를 선언할 수 있습니다.
추상 클래스는 추상 메서드를 포함할 수 있습니다.
추상 메서드가 없어도 추상 클래스로 선언할 수 있습니다.
추상 클래스는 자식 클래스에 상속되어 자식클래스에 의해서만 완성될 수 있습니다.
추상 클래스는 여러 개의 자식 클래스에서 공통적인 필드나 메서드를 추출하여 만들 수 있습니다.

추상 메서드는 인반적인 메서드와는 다르게 블록{}이 없습니다.
상속받은 클래스에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야 합니다.

인터페이스!
두 객체를 연결해주는 다리 역할을 합니다.
상속 관계가 없는 다른 클래스들이 서로 동일한 행위, 즉, 메서드를 구현해야 할 때 인터페이스는 구현 클래스들의 동일한 사용 방법과 행위를 보장해줄 수 있습니다.

interface라는 키워드를 사용하여 키워드를 선언할 수 있습니다.
모든 멤버 변수는 public static final이어야 합니다.
모든 메서드는 public abstract여야 합니다.
(Static 메서드와 default 메서드 예외)

인터페이스는 추상 클래스와 마찬가지로 직접 인스턴스를 생성할 수 없기 떄문에 클래스에 구현되어 생성됩니다.
implements 키워드를 사용하여 인터페이스를 구현할 수 있습니다.
인터페이스의 추상메서드는 반드시 오버라이딩 되어야 합니다.
만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 해당 클래스를 추상 클래스로 변경해주면 됩니다.

인터페이스간의 상속이 가능합니다.
extends 키워드를 사용합니다.
일반 클래스에서는 다중 상속이 되지 않으나 인터페이스에서는 다중 상속이 됩니다.

java 문법종합반 3주차 숙제

계산기 만들기

Step 1
더하기, 빼기, 나누기, 곱하기 연산을 수행할 수 있는 Calculator 클래스를 만듭니다.

Calulator 클래스는 연산을 수행하는 반환타입이 double인 calculate 메서드를 가지고 있습니다.
calculate 메서드는 String 타입의 operator 매개변수를 통해 연산자 매개값을 받습니다.
int 타입의 firstNumber, secondNumber 매개변수를 통해 피연산자 값을 받습니다.
calculate 메서드는 전달받은 피연산자, 연산자를 사용하여 연산을 수행합니다.

20분정도 손 가는 대로 막코드를 짜봤는데, 말이 안 된다.
강의 자료를 다시 차분히 보면서 클래스 설계부터 다시 하자.
오늘 남은 시간을 다 여기에 쓰더라도...

클래스(설계도)를 작성하는 단계

1. 클래스를 선언합니다.

public class Caculator {}

공개된 계산기 클래스 선언을 의미합니다.

2. 객체가 가지고 있어야 할 속성(필드)를 정의합니다.

    String operator; // 계산 버튼
    double result; // 결과 출력창
    int firstNumber; // 첫 입력 숫자 
    int secondNumber; // 두 번째 입력 숫자

필드와 매개 변수 구분하기
이 경우 result만 필드, 나머지는 계산을 위한 매개변수

    double result; // 결과 출력창

3. 객체를 생성하는 방식을 정의합니다.(생성자)

객체가 생성될 때 호출되며 객체를 초기화하는 역할을 수행합니다.
기본 생성자는 선언할 때 () 안에 아무 것도 넣지 않는 생성자를 의미합니다. 반면 단 하나라도 생성자가 선언되어 있다면 컴파일러는 기본 생성자를 추가하지 않습니다. 컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근 제어자를 따릅니다. (나의 경우 public으로 작성)

오타 주의

 public Calculator() {}

4. 객체가 가지고 있어야 할 행위(메서드)를 정의합니다.

 double Calculate(String operator,int firstNumber, int secondNumber) {
        if (Objects.equals(operator, "나머지")) {
            result = (double) firstNumber % secondNumber;
        }
        return result;
    }

솔직히 이렇게 쓰는 게 맞는지는 모르겠다.

더블 타입의 결과를 반환하는 Calculate 메서드 설계
String operator(더하기, 빼기, 곱하기, 나누기, 나머지로 제한 예정)
int firstNumber(첫 입력 값)
int secondNumber(두 번째 입력 값)
세 가지의 매개 변수를 통해 우선 나머지 값을 구하는 메서드를 구현해본다.

  1. 만약 첫 번째 칸에 적은 String 값이 "나머지"라면, 필드 result에 firstNumber와 secondNumber를 나눈 나머지 결과 값을 저장한다.
  2. 결과 값을 double 타입으로 변환해야 하므로 (double) 을 붙여 형 변환 한다.
  3. 그리고 그 값을 매개 변수 result에 저장하고 return한다.

step 1 코드(calculator 클래스)

package week03.homework;

import java.util.Objects;

public class Calculator {

    // 필드
    double result; // 결과 출력창

    public Calculator() {}

    //최초 나머지 연산
    double Calculate(String operator,int firstNumber, int secondNumber) {
        if (Objects.equals(operator, "나머지")) {
            result = (double) firstNumber % secondNumber;
        }
        return result;
    }

}

Test 클래스를 만들어 안에 메인 메서드를 호출하고
내 소중한 계산기 클래스 객체가 선언되는지 확인했다.
나머지 로직이 작동되는지도 확인했다.
객체 생성 잘 된다.
1단계 통과!

은근히 무작정 받아적기가 코딩할 때 도움이 된다.
순서 정리가 안 되었는데 ctrl + f 로 그냥 작성중인 글에서 키워드만 찾아도 시간 단축이 많이 된다. 내가 쓴 글이라서 친숙하기도 하고

Step 3.

step 2는 나머지 연산자 구현이어서, 앞에서 이미 했다.
AddOperation(더하기)
SubstractOperation(빼기)
MultiplyOperation(곱하기)
DivideOperation(나누기)
연산 클래스를 만든 후 클래스간의 관계를 고려하여 Calculator 클래스와 관계를 맺습니다.
관계를 맺은 후 필요하다면 Calculator 클래스의 내부코드를 변경합니다.
나머지 연산자(%) 기능은 제외합니다.
Step 2 와 비교하여 어떠한 점이 개선 되었는지 스스로 생각해 봅니다.
- hint. 클래스의 책임(단일책임원칙)

Calculator 클래스를 추상 클래스로 만들고,
저 네 클래스를 자식 클래스로 만들라는 뜻인 것 같다.

아닌 것 같다.
설계도 그림을 자세히 보니 추상화는 step 4다.
그냥 부모 자식 관계를 맺으라는 뜻 같다.

나의 원대한 계획
1. 우선 각각의 클래스에 계산기 클래스 객체를 생성한다.
2. 계산기 메서드를 사칙 연산으로 수정한다.
3. 개선점을 정리한다.

  1. 전 이렇게 객체를 생성할 거예요.
Calculator calculator = new Calculator();
  1. 계산기 메서드는 이렇게 수정했어요.
package week03.homework;

import java.util.Objects;

public class Calculator {

    // 필드
    double result; // 결과 출력창

    // 생성자 정의
    public Calculator() {}

    // 사칙연산 메서드
    double Calculate(String operator,int firstNumber, int secondNumber) {
        if (Objects.equals(operator, "더하기")) {
            result = (double) firstNumber + secondNumber;
        } else if (Objects.equals(operator, "빼기")){
            result = (double) firstNumber - secondNumber;
        } else if (Objects.equals(operator, "곱하기")) {
            result = (double) firstNumber * secondNumber;
        } else if (Objects.equals(operator, "나누기")) {
            result = (double) firstNumber / secondNumber;
        } else {
            System.out.println("잘못된 연산 명을 입력하였습니다.");
        }
        return result;
    }

}

여기가 끝이 아닌 것 같다. 이게 아닌 것 같다.
상속관계로 정의하라는 걸까. 포함 관계로 정의하라는 걸까?
설계도에는 operate(int,int) : double 로 적혀있다.
아마 Calulate에서 받았던 String 값이 여기에서는 메서드 이름으로 동작하는듯 하다. 더 깔끔한 로직으로 개선하는 과정처럼 보인다.

  • 일단 한국어를 영어로 바꾸고 오자.
  • else도 필요가 없는 것 같으니 지우자.

calculator 클래스를 상속 받고, 저렇게 메서드 형태를 더욱 단순하게 개선하라는 의미로 보인다.

예제를 참고해서 다시 해보자.
저렇게 부모 클래스에서 계산기를 다 완성해 버리면,
자식 클래스에서 형태를 바꾸기 너무 어려울 것 같다.
어떻게 관계를 맺어야 하지??????!?!?!

오버라이드가 답인가.

오버라이딩을 하기 위해서는 아래 조건들을 만족해야합니다.
1. 선언부가 부모 클래스의 메서드와 일치해야 합니다.
2. 접근 제어자를 부모 클래스의 메서드 보다 좁은 범위로 변경할 수 없습니다.
3. 예외는 부모 클래스의 메서드 보다 많이 선언할 수 없습니다.

java 기본 개념

오늘 하루를 마무리하며

오버라이딩에서 멈추다니 너무 아쉽다.
그리고 오늘 크게 느꼈다.
백 번 강의 듣는 것보다 한 번 문제 푸는 게 빨리 습득된다는 것.
내 진도가 아직도 너무 느려서
너무너무너무너무 걱정되지만
그래도 앞으로 강의는 3시간정도밖에 안 남았고
강의 듣는 것보다 코딩 하는 게 더 재밌다.
빨리 듣고 숙제 풀어야지.
내일 3주차 숙제 다 하고 4,5주차 다 들어버리고
목금토일동안 과제해야겠다.

0개의 댓글