[Lecture/Java] 04강 - 클래스와 상속(2)

김찬미·2025년 5월 27일

4강 - 클래스와 상속(2)

  • 클래스 정의와 사용
  • 상속

✅ 클래스 정의와 사용

static 필드

정적 필드 or 클래스 변수

  • 클래스의 모든 객체가 공유하는 데이터
    ✔️ 객체의 생성이 없어도 항상 사용 가능
    ✔️ 어떤 객체도 값을 변경할 수 있음
// 사용방법: 클래스이름.정적필드
// 객체변수.정적필드도 가능

class Circle {
	int x, y;
    int radius;
    static int count;
}


static 메소드

정적 메소드 or 클래스 메소드

  • non-static 메소드와 달리 객체와 무관하게 호출되고 실행됨
    ✔️ 메소드 몸체에서 this를 사용할 수 없음
    ✔️ static 메소드는 static 필드를 다룸
// 호출 방법: 클래스이름.정적메소드()
// 객체와 무관하므로 클래스 이름으로도 호출 가능
// 객체변수.정적메소드()도 가능

class Math {
	public static double sqrt(double a) {
    	...
    }
}

Math.sqrt(2.0);
Integer.parseInt("120");

final 필드와 final 메소드

final 필드

  • 상수 데이터
  • 선언할 때 초기값을 지정해야 함
  • 자주 static과 함께 사용됨
final static double PI = 3.141592;

final 메소드

자식 클래스로 상속은 가능하나 자식 클래스에서 재정의(오버라이딩)은 할 수 없는 메소드


필드의 초기화

객체를 생성할 때, 데이터 필드에 초기값을 지정하는 것

  • 데이터 필드는 자동으로 초기값(0,false,null)이 주어질 수 있음

  • 클래스 변수(static 필드)는 프로그램이 시작될 때 초기화됨

  • 객체 초기화를 위해 초기화 블록을 사용할 수 있음

    • 초기값 지정을 위한 코드로, 클래스 정의에서 메소드 바깥의 임의 위치로 들어갈 수 있음
    • static 필드는 static 초기화 블록을 사용

🔁 필드 초기화 방법의 실행 순서

  1. static 필드의 선언문에서 초기화
  2. static 초기화 블록 실행
  3. non-static 필드의 선언문에서 초기화
  4. non-static 초기화 블록 실행
  5. 생성자 실행
class IniTest {
	static int nStatic = 0;
    int nValue = 1;
    
    {
    	nValue = 2;
    }
    
    static {
    	nStatic = 1;
    }
    
    public IniTest() {
    	nValue = 3;
    }
}

메소드 오버로딩

매개변수의 개수나 매개변수의 자료형이 다르면 같은 이름의 메소드를 한 클래에서 여러 개 정의 가능

class PrintStream ... {
	public void println() {
    }
    public void println(String x) {
    }
}

✅ 상속

클래스의 재사용

🔸합성

기존 클래스를 새로운 클래스 정의에서 데이터 필드의 자료형으로 사용

  • "has-a" 관계
class Line { Point begin, end; ...}

🔹상속

기존 클래스(부모)를 사용하여 새로운 클래스(자식)를 정의

  • 코드의 중복 작성을 줄이고 프로그램의 확장성이 좋아짐
  • 상속은 기존 클래스를 확장 or 특화하는 것
  • 자식 "is-a" 부모의 관계

클래스의 상속

상속은 부모 클래스와 자식 클래스 간의 관계

  • 기존 클래스를 상속받을 때 키워드 extends를 사용함
class Manager extends Employee {...}
  • 자식 클래스에서 상속받은 메소드를 재정의(오버라이딩)할 수 있음

  • 클래스의 상속은 단일 상속만 가능

    • 인터페이스 상속의 경우 다중 상속 가능

메소드 오버라이딩

부모로부터 상속받은 메소드의 몸체를 자식 클래스에서 재정의하는 것

  • 부모와 자식에서 같은 이름의 메소드가 다른 기능을 수행하게 됨

🔁 오버라이딩 방법

  • 메소드의 이름, 인자의 개수와 자료형, 반환형이 같은 메소드를 정의

  • 단, 반환형은 서브 타입(상속 관계에서 자식 클래스)도 가능함

  • 접근 제어자의 경우, 가시성(접근 범위)는 같거나 커져야 함
    • protected인 경우, protected 또는 public만 가능
    • public인 경우, public만 가능
class Shape {
	public double getArea(double h, double w) {
    	return h * w;
    }
}

class Triangle extends Shape {
	public double getArea(double h, double w) {
    	return h * w * 0.5;
    }
}

public class Main {
	public static void main(String args[]) {
    	Shape t = new Triangle();
        System.out.println(t.getArea(3.0, 4.0));
    }
}

this

메소드 호출 시, 숨은 인자로 this가 메소드에 전달됨

  • this현재 객체에 대한 참조값을 가지고 있음
  • c1.display()c2.display()의 결과가 다른 이유

인스턴스 메소드나 생성자에서 필드를 참조하거나 메소드를 호출할 때 사용 가능(생략 가능함)

this.필드이름
this.메소드이름(인자)


super

this와 같으나 자료형이 부모 클래스 유형

  • 자식 클래스의 인스턴스 메소드나 생성자에서 사용됨
  • this와 마찬가지로 static 메소드에서는 사용 불가

부모 클래스에서 오버로딩 당한 메소드를 호출하거나 상속되었으나 감춰진 필드에 접근할 때 필요함

super.필드이름
super.메소드이름(인자)


thissuper의 사용 예

class CSuper {
	public double x;
}

class CSub extends CSuper {
	public double x;
    
    public CSub(double new_x) {
    	this.x = new_x;
        super.x = new_x * 10;
    }
    
    public double getSuper() {
    	return super.x;
    }
    
    public double getSub() {
    	return this.x
    }
}


public class Main {
	public static void main(String args[]) {
    	CSub sub = new CSub(10.0);
        System.out.println(sub.x); // 10.0
        System.out.println(sub.getSuper()); // 100.0
        System.out.println(sub.getSub()); // 10.0
    }	
}

상속과 생성자

this

  • 같은 클래스의 다른 생성자를 호출하는 것

super

  • 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출하는 것
    ✔️ 상속받은 데이터 필드를 초기화하기 위해 사용

  • 자식 클래스의 생성자 몸체에서 부모 클래스 생성자의 명시적 호출이 없다면, 인자가 없는 생성자인 super()가 자동 호출됨

  • this()super()생성자 몸체의 맨 앞에 위치해야 함

메소드 체이닝

하나의 명령문에서 동일 객체에 대해 연속적으로 메소드 호출을 하는 프로그래밍 기법

  • 메소드 체이닝에 사용되는 메소드는 현재 객체의 참조값(this)를 반환해야 함
  • 메소드 체이닝은 프로그램의 가독성을 향상시키고, 코딩을 단순화함
p.setName("홍길동").setAge(30).setAddress("서울");

profile
백엔드 지망 학부생

0개의 댓글