[혼공자]3주차

박수연·2025년 7월 24일
0

[혼공자]

목록 보기
3/7

06. 클래스

06-1 객체 지향 프로그래밍

  • 객체 : 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있으면서 식별 가능한 것
  • 객체는 필드와 메소드로 구성

객체의 상호작용

  • 객체는 독립적으로 존재하고, 다른 객체와 메소드를 통해 상호작용 한다
  • 메소드 호출 방법 ↓
    리턴값 = 전자계산기객체.메소드(매개값1, 매개값2, …);
  • 객체에 도트 연산자(.)를 붙이소 메소드 이름 기술
  • 매개값은 메소드를 실행하기 위해 필요핟 데이터

객체 간의 관계

① 집합 관계 ex) 자동차 - 핸들, 엔진, 타이어, ...
② 사용 관계 ex) 사람 - 자동차: 달린다, 멈춘다, ...
③ 상속 관계 : 상위 하위 객체를 생성하는 관계 ex) 기계 - 자동차

객체와 클래스

  • 클래스 : 객체를 생성하기 위한 필드와 메소드가 정의되어 있음
  • 인스턴스 : 클래스로부터 만들어진 객체(클래스로부터 객체를 만드는 과정 '인스턴스화')
  • 객체지향 프로그래밍 개발 3단계
    ①클래스 설계 ②객체 생성 ③객체 이용

클래스 선언

  • 식발자 작성 규칙
    • 하나 이상의 문자로 구성
    • 첫 글자에 숫자 사용 불가
    • '$', '_' 이외 특수문자 사용 불가
    • 자바 키워드 사용 불가
  • 클래스 이름은 한글도 가능하지만 한글로 만드는 경우는 거의 없음
  • 영어 대소문자 구분
  • 단일 단어일 경우 보통 첫글자는 대문자 나머지는 소문자, 여러 단어일 경우 각 단어의 첫글자는 대분자 나머지는 소문자
  • 클래스 이름 정하고 난 후 클래스이름.java 파일 생성
public class 클래스 이름 {
system.out.println("Hello, JAVA");
}
  • 일반적으로 1개의 소스파일당 하나의 클래스를 선언하고, 이 소스파일을 컴파일하면 하나의 바이트 코드 파일(.class)이 생성된다
  • 소스파일에 2개 이상의 클래스를 선언할수 있다. 이 경우 컴파일 하면 2개 이상의 바이트 코드 파일(.class)이 생성된다(1클래스 당 1 바이트코드파일)

객체 생성과 클래스 변수

  • 클래스로부터 객체를 생성할 때 new 연산자 사용
    new 클래스();
  • new 연산자를 사용하면 메모리 힙영역에 객체가 생성된다
  • ↓클래스로 선언된 변수에 new 연산자를 이용하여 객체의 메모리 내 위치를 저장
클래스 변수;
변수 = new 클래스();

클래스 변수 = new 클래스();

Student와 StudentExample 클래스의 용도

  • 클래스의 두 가지 용도
    ①라이브러리 ②실행용
  • Student 클래스는 라이브러리 클래스, StudentEample 클래스는 실행 클래스
public class Student{

}

public class StudentExample{
	public static void main(String[] args){
    	Student s1 = new Student();
        System.out.println("s1 변수가 Student 객체를 참조합니다.");
        
        Student s2 = new Student();
        System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다.");
    }
}
  • Student 클래스에 main() 메소드를 작성해 라이브러리인 동시에 실행 클래스로 만들 수도 있다
  • 라이브러리인 동시에 실행클래스로 만들 수 있지만 가급적 두 클래스를 분리해서 작성

클래스의 구성 멤버

public class ClassName{
  // 필드
  int filedname;

  // 생성자
  ClassName(){…}

  //메소드
  void methodName(){…}
}

필드

  • 객체의 데이터가 저장되는 곳

생성자

  • 객체 생성 시 초기화 역할 담당

메소드

  • 객체의 동작에 해당하는 실행 블록

06-2 필드

  • 필드 : 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳

필드 선언

타입 필드 = 초기값;

  • 필드 선언은 클래스 중괄호{} 블록 어디서든 가능, 생성자 또는 메소드 중괄호{} 블록 내부에서는 X
  • 모든 타입 가능
  • 초기값이 지정되지 않을 경우 자동으로 기본 초기값으로 설정

필드 사용

  • 필드값을 읽고 변경하는 작업
  • 클래스 내에서는 필드 이름으로 읽고 변경
  • 클래스 외부에서는 객체 생성 후 필드 사용
public class Car {
	// 필드
    int speed; ← 초기값X, 기본값 0으로 저장되어 있음
    
    // 생성자
    Car(){
    	speed = 0;
    }
    
    // 메소드
    void method(...){
    	speed = 10;
    }
}

public class Person{
// Car 객체 생성
Car myCar = new Car();

// 필드 사용
myCar.speed = 60;

}
  • Person 클래스의 myCar 변수가 Car 객체를 참조하게 되면 도트(.)연산자를 사용해서 speed 필드에 접근 가능

06-3 생성자

  • new연산자로 호출되는 중괄호 블록
  • 객체 생성 시 초기화 담당
  • 모든 클래스에 반드시 하나 이상 존재
  • 객체 초기화 : 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는것
    (객체 초기화를 해야 메모리의 힙 영역에 객체가 생성되고 객체의 번지가 리턴된다)

기본 생성자

public 클래스() {}

  • 중괄호{} 블록 내용이 비어있는 생성자
  • 클래스 내에서 생성자를 선언하지 않을 경우 기본생성자가 자동으로 생성됨(생성자가 1개라도 있을 경우 기본 생성자를 자동으로 추가하지 않음)

생성자 선언

클래스( 매개변수 선언, …) {
	// 객체의 초기화 코드
}
  • 클래스 이름과 동일하고 리턴 타입이 없다

필드 초기화

  • 클래스로부터 객체가 생성 될 때 필드는 기본 초기값으로 자동 설정
  • 다른 값으로 초기화 하고 싶을 경우
    ①필드 선언 시 초기값 지정 ②생성자에서 초기값 지정

생성자 오버로딩

  • 변수를 다르게 하는 생성자를 여러 개 선언하는 것
public class Car{
  Car(){…} 										   ←생성자
  Car(String model){…} 							   ←생성자
  Car(String model, String color){…} 			   ←생성자
  Car(String model, String color, int maxSpeed){…} ←생성자
}
  • 매개변수의 타입과 개수, 선언 순서가 똑같은 경우 생성자 오버로딩X
  • new 연산자로 생성자를 호출 할 때 제공되는 매개값의 타입과 수에 의해 호출되는 생성자 결정

다른 생성자 호출 : this()

  • 생성자 오버로딩이 많아지면 코드가 중복되므로, 필드 초기화는 한 생성자에서 코드를 작성하고 나머지 생성자는 코드를 가진 생성자를 호출하는 방법을 사용하는데 이때 this()를 사용
public class Car {
	//필드
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	//생성자
	Car() {
	}
	
	Car(String model) {
		this(model, "은색", 250); ←마지막 생성자 호출
	}
	
	Car(String model, String color) {
		this(model, color, 250); ←마지막 생성자 호출
	}
	
	Car(String model, String color, int maxSpeed) {
		this.model = model;			 ─┐
		this.color = color;			  │ 필드 초기화 공통 실행 코드
		this.maxSpeed = maxSpeed;	 ─┘
	}
}

06-4 메소드

  • 객체의 동작을 나타내는 부분

메소드 선언

  • 리턴 타입 : 메소드 실행 결과값(리턴값)의 타입(리턴값은 있을수도 있고 없을 수도 있음)
void powerOn(){…} ← 리턴값이 없는 경우
double divide(int x, int y){…} ← 리턴값이 있는 경우, 리턴 타입 double
  • 리턴 타입과 다른 타입의 변수에 메소드 결과를 저장할 경우 컴파일 에러 발생
    int result = divide(10, 20);

메소드 이름

  • 규칙
    • 숫자로 시작X, '$'와 '_'만 사용가능
    • 관례적으로 소문자로 작성
    • 여러 단어 혼합된 경우, 두번째부터 단어의 첫글자는 대문자

매개변수 선언

  • 메소드를 실행할 때 외부로부터 필요한 데이터를 받기 위해 사용
double divide(int x, int y){…}
double result = divide(10.5, 20.0); ←이런 경우 컴파일 에러 발생
byte b1 = 10;
byte b2 = 20;
double result = divide(b1, b2); ←이런 경우에는 byte가 int로 자동 타입 변환되므로 컴파일에러 발생x

매개 변수의 개수를 모를 경우

  • 매개 변수를 배열타입으로 선언하여 해결
    ex) int sum1(int[] values){} ←메소드 호출 전 배열 생성해야하므로 번거로울 수 있음
  • … 사용
    ex) int sum2(int … values){}
    int result = sum2(1, 2, 3); ←메소드 호출 시 쉼표 이용하여 매개변수 값 나열
    int result = sum2(1, 2, 3, 4, 5);

리턴(return)문

리턴값이 있는 메소드

  • 리턴값이 있는 메소드는 리턴문을 이용해 리턴값 지정
    ex) return 리턴값;
  • 리턴값이 있는 메소드인데 리턴문이 없으면 컴파일 에러 발생
  • 리턴문 실행 즉시 메소드 종료

리턴값이 없는 메소드 : void

  • 리턴값이 없는 메소드는 리턴 타입으로 void를 사용
  • 이런 경우 return문을 사용하는 즉시 메소드 종료

메소드 호출

객체 내부에서 호출

  • 메소드(매개값, …);

객체 외부에서 호출

  • 클래스로부터 객체 생성 후 호출
클래스 참조변수 = new 클래스(매개값, …);
참조변수.메소드(매개값, …); ←리턴값이 없거나, 리턴값을 받지 않을 경우
타입 변수 = 참조변수.메소드(매개값, …); ←리턴값이 있고, 리턴값을 받고 싶을 경우

메소드 오버로딩

  • 같은 이름의 메소드를 여러 개 선언하는 것
class 클래스 { 
리턴 타입 	메소드이름 (타입 변수, …){…}
	↑			↑		  ↑
상관없음		   동일		매개변수의 타입, 개수, 순서가 달라야함
	↓			↓		  ↓
리턴 타입 	메소드이름 (타입 변수, …){…}
}

06-5 인스턴스 멤버와 정적 멤버

인스턴스 멤버와 this

  • 인스턴스 멤버 : 객체 생성 후 사용할수 있는 필드와 메소드, 각각 인스턴스 필드 인스턴스 메소드라고 부름

인스턴스 멤버 선언

public class Car {
	// 필드
    int gas;
    
    // 메소드
    void setSpeed(int speed){…}
}

this

  • 객체 내부에서 인스턴스 멤버에 접근하기 위해 사용 가능
  • 객체 스스로를 가리킴
  • this.model 이라고 하면 객체가 가지고 있는 model 필드를 뜻함

정적 멤버와 static

  • 정적 멤버 : 클래스에 고정된 멤버로 객체를 생성하지 않고 사용할 수 있는 필드와 메소드

정적 멤버 선언

  • static 키워드를 붙여 선언;
public class Calculator{
  String color;												// 인스턴스 필드
  void setColor(String color){ this.color = color; }		// 인스턴스 메소드
  static double pi = 3.14159;								// 정적 필드
  static int plus(int x, int y){ return x + y; }			// 정적 메소드
  static int minus(it x, int y){ return x - y; }			// 정적 메소드
}

정적 멤버 사용

  • 클래스가 메모리로 로딩되면 바로 사용 가능
double result = 10*10*Calculator.pi;
int result2 = Calculator.plus(10, 5);
int result2 = Calculator.minus(10, 5);
  • 정적 필드와 정적 메소드는 원칙적으로 클래스 이름으로 접근해야 하지만 객체 참조 변수로도 접근 가능(but 클래스명으로 접근하는게 좋음)
Calculator myCalcu = new Calculator();
double result = 10*10*myCalcu.pi;
int result2 = myCalcu.plus(10, 5);
int result2 = myCalcu.minus(10, 5);

정적 메소드 선언 시 주의할 점

  • 객체가 없어도 실행되므로 정적 메소드 선언 시 내부 인스턴스 필드나 인스턴스 메소드 사용 불가(인스턴스 멤버를 사용하려면 객체 선언후 참조변수로 접근)

싱글톤

  • 전체 프로그램에서 단 하나만 만들어지도록 보장하는 객체
  • 생성자 앞에 private를 붙여 외부에서 접근하는것을 막음
public class 클래스 {
  // 정적 필드
  private static 클래스 singleton = new 클래스();

  // 생성자
  private 클래스() {}

  // 정적 메소드
  static 클래스 getInstance() {
    return singleton;
  }
}
  • 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는것
  • 각각 다른 변수에서 getInstance()를 호출하더라도 같은 객체만 리턴하므로 각각의 변수는 동일한 객체를 참조

final 필드와 상수

final 필드

  • final 필드에 초기값이 저장되면 프로그램 실행 도중에 수정할 수 없음
  • final 필드에 초기값 지정하는 방법
    ①필드 선언시 ②생성자에서 지정
  • 초기화 되지 않은 final필드가 남아있을 경우 컴파일 에러 발생

상수

  • 일반적으로 불변의 값을 저장하는 필드를 말함
    static final 타입 상수 = 초기값;
  • 이름은 모두 대문자로 작성하는것이 관례, 단어가 혼합된 경우 언더바(_)로 단어 연결
static final double PI = 3.14159;
static final double EARTH_RADIUS = 6400;
static final double EARTH_AREA = 4*Math.PI*EARTH_RADIUS*EARTH_RADIUS;

06-6 패키지와 접근 제한자

  • 패키지 : 파일 시스템의 폴더 형태를 하는 클래스의 일부분으로 클래스를 유일하게 만들어주는 식별자 역할을 한다
  • 클래스 이름이 같더라도 패키지가 다르면 다른 클래스로 인식
  • 상, 하위로 구분된 패키지는 도트(.)를 사용해 표현 가능
    상위패키지.하위패키지.클래스

패키지 선언

package 상위패키지.하위패키지;

public class ClassName(){}
  • 패키지 이름 규칙
    • 숫자로 시작X, '$'와 '_'만 사용가능
    • java로 시작하는 패키지는 자바표준 API에서만 사용가능하므로 사용 불가
    • 모두 소문자로 작성하는것이 관례

접근 제한자

  • 접근을 제한하기위해 사용
  • 종류
    • public 접근 제한자 : 외부 클래스가 자유롭게 사용 가능
    • protected 접근 제한자 : 같은 패키지 또는 자식 클래스에서 사용 가능
    • private 접근 제한자 : 외부에서 사용 불가
    • default 접근 제한 : 접근 제한자가 적용되지 않을 경우, 같은 패키지에 소속된 클래스에서만 사용 가능

클래스의 접근 제한

// default 접근 제한
class 클래스 { … }

// public 접근 제한
public class 클래스 { … }

default 접근 제한

  • 클래스 선언 시 public 생략 한 경우
  • 같은 패키지 내에서는 사용 가능, 다른 패키지에서는 사용 불가

public 접근 제한

  • 같은 패키지 뿐만 아니라 다른 패키지에서도 제한 없이 사용 가능

생성자의 접근 제한

public class ClassName{
  // public 접근 제한
  public ClassName( … ){ … } 

  // protected 접근 제한
  protected ClassName( … ){ … }

  // default 접근 제한
  ClassName( … ){ … }

  // private 접근 제한
  private ClassName( … ){ … }
}
  • public 접근 제한 : 모든 패키지에서 아무란 제한 없이 생성자 호출 가능
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 생성자 호출 가능, 다른 패키지에 속한 클래스가 자식클래스라면 생성자 호출 가능
  • default 접근 제한 : 같은 패키지 내에서 호출 가능
  • private 접근 제한 : 생성자 호출X, 클래스 내부에서만 생성자 호출 가능, 객체 생성 가능

필드와 메소드의 접근 제한

// 필드 선언 
[public | protected | private] [static] 타입 필드;

// 메소드 선언
[public | protected | private] [static] 리턴타입 메소드( … ) { … };
  • public 접근 제한 : 모든 패키지에서 아무란 제한 없이 필드와 메소드 사용 가능
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 필드와 메소드 사용 가능, 다른 패키지에 속한 클래스가 자식클래스라면 필드와 메소드 사용 가능
  • default 접근 제한 : 같은 패키지 내에서 필드와 메소드 사용 가능
  • private 접근 제한 : 필드와 메소드 사용 불가, 클래스 내부에서만 사용 가능

Getter와 Setter 메소드

  • 필드를 외부에서 접근하지 못하도록 막고, 메소드를 공개해 외부에서 메소드를 통해 필드에 접근하도록 유도하는것
privat 타입 fieldName;

  // Getter
  public 리턴 타입 getFieldName(){
    return fieldName;
  }

  // Setter 
  public void setFieldName(타입 fieldName){
    this.fieldName = fieldName;
  }

과제

  • 기본과제
    이미 용어 정리는 위에 다 되어 있지만 그 중에서 이건 잊으면 안된다 정말 중요하다 생각하는것만 골라서 다시 한번 체크
    - 객체 : 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있으면서 식별 가능한 것
    - 클래스 : 객체를 생성하기 위한 필드와 메소드가 정의되어 있는것, 클래스로부터 객체를 생성할 때 new 연산자 사용
    - 필드 : 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳으로 모든 타입이 가능. 초기값이 지정되지 않을 경우 해당 타입의 기본 초기값으로 설정된다
    - 생성자 : 객체 생성 시 초기화 시키는 메소드, new 연산자로 호출되며 모든 클래스에 반드시 하나 이상 존재한다. 생성자를 선언하지 않을 경우 자동으로 만들어지는 중괄호 블록이 비어있는 생성자
    - 메소드 : 객체의 동작에 해당하는 실행 블록으로 리턴 타입 메소드명 (매개변수, ...){내부 코드}로 구성
    - 인스턴스 멤버 : 객체 생성 후 사용 가능한 필드와 메소드
    - 정적 멤버 : 클래스에 고정된 멤버로 객체를 생성하지 않고도 사용 가능한 필드와 메소드
    - 패키지 : 파일 시스템 폴더 형태를 하는 것으로 클래스를 유일하게 만들어주는 식별자
    - 접근 제한자 : 클래스, 생성자, 필드, 메소드에 접근 제한하기 위한 용어. public, protected, default, private 이렇게 네 가지 접근 제한 종류가 있고 default는 나머지 세가지 접근 제한자를 사용하지 않은 경우 적용된다

셋째주 느낀점
지각쟁이가 되어버렸다. 마음은 미리미리 해야지 하는데 잘 되지 않는다. 다른 사람들의 숙제를 보면서 나도 저 사람들처럼 잘 하고싶다 라고 생각하지만 현실은 항상 부족한 느낌
참여하는 것만으로도 큰 의미가 있다고 생각하지만 잘하고 싶은건 큰 욕심일까
일단 하고 조금씩 수정과 보완을 거쳐가자고 되뇌이지만 한번에 잘하고 싶다 이거 완전 욕심쟁이네
매번 다짐하지만 어제보다 나은 내가 되자 다음에는 지각하지 말자!

0개의 댓글