[혼공자바] 3주차 공부기록(클래스)

Say·2025년 7월 23일
0
post-thumbnail

객체 지향 프로그래밍

객체란?

  • 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중..
    • 자신의 속성을 가지고 있는 것.
    • 식별 가능한 것.
  • 속성 & 동작
    • 속성: 나이, 이름 등..
      • 필드
    • 동작: 웃다, 먹다 등..
      • 메소드
  • 객체 모델링
    • 소프트웨어 객체의 필드와 메소드로 정의

객체의 상호작용

  • 독립적: 객체들은 각각 독립적으로 존재
  • 상호작용: 다른 객체와 서로 상호작용하면서 동작
    • 수단: 메소드
    • 메소드 호출: 객체가 다른 객체의 기능을 이용하는 것

객체의 간의 관계

객체를 A, B라고 칭하겠다.

  • 집합 관계
    • A → 부품, B → 완성품
  • 사용 관계
    • A, B간의 상호작용
  • 상속 관계
    • B(부모 객체) 기반으로 A(자식 객체)를 생성
    • 부모 객체 → ‘종류’, 자식 객체 → ‘구체적인 사물’

객체와 클래스

  • 클래스
    • 객체를 생성하기 위한 필드와 메서드 정의
  • 인스턴스
    • 클래스로부터 만들어진 객체
  • 하나의 클래스로부터 여러 개의 인스턴스를 만들 수 있다.

클래스 선언

  • 선언 방법
public class Car {

}

public 접근 제한자?

→ 파일 이름과 동일한 이름의 클래스 선언에만 붙일 수 있다.

소스 파일당 하나의 클래스를 선언하는 것이 일반적!

한 파일에 두개 이상의 클래스를 선언 못하는 것은 아니다.

소스 파일은 그냥 클래스 선언을 담고 있는 저장 단위일뿐..

객체 생성과 클래스 변수

  • 클래스 선언 → 컴파일 → 객체 생성 가능!
  • 객체 생성하기
    new 클래스();
    new → 객체 생성 연산자. (2주차에서 이를 사용한 과제를 진행했었다!) new 연산자로 생성된 객체 → 메모리 힙 영역에 생성
    Car 변수 = new Car();
    Scanner scanner = new Scanner(System.in);
    ✅ new 연산자로 객체를 생성하고 객체의 주소를 변수에 저장해야 변수가 객체를 잘 참조할 수 있다!! 객체 생성만 띡하고 끝내면 안된다.

클래스의 구성 멤버

  • 구성멤버
    • 필드
      • 객체의 고유 데이터, 상태 정보 저장
      • 객체가 소멸되지 않는 한 객체와 함께 존재
    • 생성자
      • new 연산자로 호출
      • 역할
        • 객체 생성 시 초기화 담당
          • 필드 초기화 OR 메소드 호출 → 객체 사용 준비
    • 메소드
      • 객체의 동작에 해당하는 중괄호 블럭
      • 필드 읽기/수정
      • 다른 객체 생성 → 다양한 기능 수행
      • 객체 간의 데이터 전달 수단

필드

필드?

  • 객체의 고유 데이터, 객체의 현재 상태 데이터 저장하는 곳

필드 선언

  • 타입 → 필드에 저장할 데이터의 종류 결정
  • 기본타입과 참조타입 올 수 있음
  • 필드의 초기값 → 필드 선언 시 주어질수도.. 생략될수도..

필드 사용

  • 필드값을 읽고 변경한다.
  • 도트 연산자 사용해서 필드에 접근할 수 있다.
    Car myCar = new Car();
    // Car 클래스의 필드에 int speed; 가 있다고 가정
    myCar.speed = 60; 

생성자

생성자

  • new 연산자 → 클래스로부터 객체 생성 시 호출되어 객체의 초기화 담당

객체 초기화

  • 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것.
  • ⭐️생성자 실행하지 않고 객체를 만들 수 없음!!!!!!
    • new 연산자에 의해 객체 성공적 생성 → 힙 영역에 객체 생성

기본 생성자

  • 모든 클래스는 생성자가 반드시 존재.
  • 생성자 하나 이상 가질 수 O

명시적으로 생성자를 선언하는 이유?

→ 객체를 다양한 값으로 초기화하기 위해!

생성자 선언

public class Car {
	...
	Car(String model, int speed, String color) {}
}

public class CarExample {
	Car myCar = new Car("벤츠", 180, "검정");
}

클래스에 생성자가 명시적으로 선언되어있을 경우에는 반드시 선언된 생성자를 호출해서 객체를 생성해야한다.

필드 초기화

  • 객체 생성 시점에 외부에서 제공되는 다양한 값들로 초기화 되어야한다?
    • 생성자에서 초기화하기
      public class Korean {
      	String nation = "대한민국";
      	String name;
      	int age;
      	
      	// 생성자
      	public Korean(String name, int age) {
      		this.name = name;
      		this.age = age;
      	}
      }
      Korean say = new Korean("세이", 20);
      Korean ho = new Korean("호", 20);
      🤔 this 가 뭐야? - 필드와 매개변수 이름이 동일하면 생성자 내부에서 해당 필드에 접근할 수 없다. - 동일한 이름의 매개변수의 우선순위가 더 높아서! - 그래서 자기 자신의 참조를 나타내는 ‘this’를 사용!

생성자 오버로딩

🤔 생성자 오버로딩이 왜 필요할까?

객체가 생성될 떼 외부에서 제공되는 데이터가 없다면 기본 생성자로 객체를 생성해야한다.

또한 데이터가 따로따로 각각 제공될때도 객체를 생성할 수 있어야한다.

근데 생성자가 하나뿐이라면 그 형식에 맞춰서만 데이터를 보낼 수 있기에 위와 같은 요구조건을 수용할 수 없다.

따라서 다양한 방법으로 객체를 생성할 수 있도록 생성자 오버로딩이 필요하다!

  • 생성자 오버로딩이란?
    • 매개변수를 달리하는 생성자를 여러 개 선언하는 것.
  • 매개 변수의 타입과 개수, 선언된 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 생성자 오버로딩이 아니다.
public class Car {
	String model;
	String color;
	int speed;
	
	Car() {}
	
	Car(String model) { this.model = model; }
	
	Car(String model, int speed) { 
		this.model = model; 
		this.speed = speed;
	}
}

메소드

메소드 시그니처

  • 메소드 선언부

메소드 선언

  • 매개변수의 개수를 모를 경우
    public class Computer {
    	int sum1(int[] values) {
    		int sum = 0;
    		for(int i = 0; i < values.length; i++) {
    			sum += values[i];
    		}
    		return sum;
    	}
    	
    	int sum2(int ... values) {
    		int sum = 0;
    		for(int i = 0; i < values.length; i++) {
    			sum += values[i];
    		}
    		return sum;
    	}
    	
    }
    int sum2(int ... values) -> 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용된다.

인스턴스 멤버와 정적 멤버

인스턴스 멤버와 this

  • 인스턴스 멤버
    • 객체를 생성한 후 사용할 수 있는 필드와 메소드
    • 객체에 소속된 멤버 → 객체 없이 사용 불가
    • 인스턴스 메소드
      • 객체에 소속된 멤버지만 객체 내부에 존재하지 않고 메소드 영역에 저장되고 공유.
        • 코드 블록이기에 객체마다 동일한 코드 블록을 가지고 있을 필요가 없다.
  • this
    • 객체 내부에서 인스턴스 맴버에 접근하기 위해 사용
    • 주로 생성자와 메소드의 매개변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시하고자 할 때 사용

정적 멤버와 static

  • 정적 멤버 → 클래스에 고정된 멤버.
    • 객체 생성하지 않고 사용할 수 있는 필드와 메소드
  • 선언 방법
    • ‘static’ 키워드를 추가적으로 붙인다.

      public class Calculator {
      	String color;
      	static double pi = 3.14159;
      }
  • 주의 사항
    • 객체가 없어도 실행된다는 특징
      • 메소드 선언 시 내부에 인스턴스 필그나 인스턴스 메서드를 사용할 수 없음
      • 객체 자신의 참조인 this 키워드도 사용 불가
      • 그래도 사용하고 싶다면?
        • 객체를 먼저 생성하고 참조 변수로 접근하기

싱글톤

  • 단 하나의 객체만 만들도록 보장
  • 클래스 외부에서 new 연산자로 생성자를 호출할 수 없어야한다.
  • private 사용

final 필드와 상수

final

  • 저장된 초기값 → 최종값
    • 수정 X
    • 한 번 값이 저장되면 변경할 수 없도록 final 필드로 선언

상수

  • 불변의 값 → static final
  • final 필드는 객체마다 저장되고 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있기에 상수가 될 수 없다.
  • static final 필드는 객체마다 존재하지 않고 클래스에만 존재.

패키지와 접근 제한자

접근 제한자

  • 접근을 제한하기 위해 사용
  • 예시
    • public 접근 제한자
      • 외부 클래스가 자유롭게 사용 가능
    • private 접근 제한자
      • 같은 패키지 또는 자식 클래스에서 사용 가능
    • protected 접근 제한자
      • 외부에서 사용 불가
    • default 접근 제한자
      • 같은 패키지에 소속된 클래스에서만 사용 가능

Getter & Setter

  • 일반적으로 객체지향프로그래밍에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는 것을 막는다.
    • 무결성이 깨질수도 있기 때문에..
    • 이러한 문제점을 해결하기 위해 → 메소드를 통해 필드 변경 방법 선호
      • 매개값 검증 → 유효한 값만 객체의 필드로 저장 ➡️ Setter
    • 외부에서 객체의 데이터를 읽을 경우에도 메소드 사용 good
      • 필드값을 직접 사용하면 부적절한 경우도 있기에..
      • 필드값 가공 후 외부로 전달 ➡️ Getter

이번 주차에는 용어가 쏟아질 듯이 많이 나와서 이렇게 정리를 했다.
뜻과 예시 위주로 정리를 해보는 주차였다-!

[추가] 객체 지향 프로그래밍?

자바와 '객체'는 서로 떼어내려고 해도 항상 같이 붙어다니는 수식어 같은 느낌이다.

우리는 왜 객체지향 프로그래밍을 하는 것일까?

구조적 설계를 통한 안정적인 구조를 구축하기 위해서라고 할 수 있다.
구조적 설계의 핵심은 작은 단위로 나누는 것!

근데 잘못 나누면 오히려 수정하기 어려울 수도 있기 때문에
무조건적으로 객체지향이 좋은 것만은 아닌..
적재적소에 맞게 나눠 사용해야한다.

객체가 어떤 역할을 하는지, 어떤 책임을 가지고 있는지를 기반으로 설계를 하면 나중에 재사용과 변경에 유연하게 작용할 수 있다.

자율성을 가진 객체들을 서로 잘 협력하며 사용할 수 있도록
분할하는 설계가 객체 지향 프로그래밍이라고 볼 수 있다.

객체끼리의 역할, 책임을 적절하게 나누는 것이 중요하다.
객체 혼자 너무 많은 비지니스 로직을 포함하지 않게 설계하는 것이 중요!

profile
Say Hi!

0개의 댓글