dev-course day4

2rlokr·2025년 3월 7일

dev-course

목록 보기
4/43

오늘 배운 내용

OOP와 자바

패러다임 (Paradigm)

인식의 체계, 사물에 대한 인식이나 생각의 틀, 체계

프로그램을 만드는 데에도 패러다임이 있다.

객체지향 패러다임 (Object Oriented Paradigm)

  • 소프트웨어 개발의 패러다임
  • 자바가 객체지향 패러다임을 따라가는 대표적인 프로그래밍 언어
  • 프로그램을 객체(Object)라는 기본 단위로 구성하고 문제를 풀어나간다.
  • 여기서 객체란, 프로그램에서 필요한 데이터를 추상화한 것 (상태와 행위를 추상화)

객체지향의 4가지 특징

객체 지향 프로그래밍에는 네 가지 특징이 있다.
1. 캡슐화 (Encapsulation)
2. 상속 (Inheritance)
3. 다형성 (Polymorphism)
4. 추상화 (Abstraction)

추상화 (Abstraction)

  • 필요한 정보만 남기고 세부사항을 감추는 것
  • 복잡한 시스템의 중요한 내용은 보여주고, 불필요한 세부 사항은 숨기는 원칙
  • 객체가 공통적으로 수행할 수 있는 기능을 정의하고, 이 기능에 대한 세부 사항은 숨긴다. Java에서는 추상 클래스 (abstract class)와 인터페이스(interface)를 통해 추상화를 구현한다.

EX) 전화하는 것, 문자 보내는 것 어떻게 되는 건지 알고 보내는가? NO!
사용자 인터페이스만 보게 된다.

  • 추상 클래스는 일부 메서드가 구현되지 않고, 서브 클래스에서 이 메서드를 구현해야 하는 클래스를 의미한다.
  • 인터페이스는 메서드의 시그니처만 정의하고, 실제 구현은 이를 구현하는 클래스에서 제공된다.
  • 추상화를 통해 시스템의 복잡성을 줄이고, 시스템을 보다 직관적으로 모델링할 수 있다.

캡슐화 (Encapsulation)

  • 객체의 데이터와 그 데이터를 처리하는 메소드를 하나로 묶어서 외부로부터 객체의 내부 구현을 숨기는 원칙
  • 객체의 상태(데이터)는 외부에서 직접 접근하거나 변경할 수 없으며, 객체가 제공하는 공용 메서드를 통해서만 데이터를 조작할 수 있다.
  • 데이터의 무결성을 유지하고, 객체의 내부 구현을 변경하더라도 외부 코드에 미치는 영향을 최소화한다.
  • private, protected, public 과 같은 접근 제어자를 활용해 구현하고, 메서드를 보호
  • getter, setter을 사용하는 이유도 동일
    - getter는 열려있고, setter가 닫혀있으면 => 읽기 전용이라고 부른다.
  • 객체의 세부 사항을 은닉하고 외부 인터페이스만을 통해 상호작용하도록 한다.

상속 (Inheritance)

  • 기존의 클래스(부모 클래스)를 바탕으로 새로운 클래스(자식 클래스)를 생성
  • 부모 클래스의 속성과 메서드를 자식 클래스가 재사용할 수 있도록 한다.
  • 코드의 재사용성을 높이고, 계층적인 관계를 통해 객체 관의 관계를 명확히 한다.
  • 자식 클래스는 부모 클래스의 모든 특성을 상속받는다.
  • 추가적인 속성이나 메서드를 정의하거나, 기존의 메서드를 수정(오버라이딩)할 수 있다.

다형성 (Polymorphism)

  • 동일한 메서드 이름이지만, 다양한 형태로 구현될 수 있는 기능
  • 메서드 오버로딩과 메서드 오버라이딩으로 구현

메서드 오버로딩

같은 이름의 메서드를 매개변수의 타입이나 개수(메서드 시그니처)에 따라 다르게 정의

메서드 오버라이딩

상속받은 메서드를 자식 클래스에서 재정의하여 구체적인 동작을 정의

  • 코드의 확장성과 재사용성을 높여준다.

객체 (Object)

  • 프로그램을 구성하는 기본 단위
  • 데이터와 이을 처리하는 메서드를 하나로 묶어놓은 하나의 실체(개체)
  • 상태(State)와 행동(Behavior)로 구성

상태 (State)

객체가 가지는 속성(Property)이나 데이터, 객체의 내부 상태를 정의

행동 (Behavior)

객체가 수행할 수 있는 동작, 객체의 메서드를 통해 구현

붕어빵 : 개념 -> 객체
붕어빵 안에 팥 or 슈크림 -> 상태
붕어빵을 만들기 위해 달궈놓은 틀 -> 클래스
붕어빵 틀로 나온 실제 붕어빵 -> 인스턴스

  • 객체는 캡슐화를 통해 데이터와 메서드를 하나로 묶어 외부로부터 객체의 내부 구현을 숨기고, 객체가 제공하는 인터페이스를 통해서만 상호작용할 수 있다.
  • 다형성과 상속을 통해 객체와의 관계를 정의하고, 프로그램의 기능을 확장하거나 수정할 수 있다.

클래스 (Class)

  • 객체의 상태를 나타내는 필드(변수)와 객체의 동작을 정의하는 메서드로 구성
  • 추상화를 통해 데이터와 메서드를 하나의 단위로 묶어준다.

변수 (Field)

  • 객체의 상태를 표현
  • 클래스의 속성 (Property)를 나타내는 변수
  • 클래스의 인스턴스가 가지는 데이터를 저장하며, 인스턴스 변수와 정적 변수로 나뉜다.
  • 인스턴스 변수는 각 객체가 독립적으로 가지는 데이터이며, 정적(static)변수는 클래스 자체에 속하며 모든 객체가 공유

함수 (Method)

  • 객체의 행동을 표현
  • 클래스의 동작을 정의하는 함수
  • 객체의 상태를 변경하거나 특정 작업을 수행

인스턴스 (Instance)

클래스를 바탕으로 생성된 구체적인 객체

생성자 (Constructor)

  • 객체를 초기화하는 특별한 종류의 메서드
  • 클래스의 인스턴스를 생성할 때 호출되며, 객체의 초기 상태를 설정하는 데에 사용
  • 반환 타입이 존재하지 않는다.
  • 생성자는 오버로딩을 통해 여러 생성자를 정의할 수 있으며, 각각의 생성자별로 인스턴스가 보유할 수 있는 값들이 달라진다.

기본 생성자

매개변수가 없는 생성자를 기본 생성자라고 한다. 기본생성자는 컴파일러(javac)에 의해 자동으로 정의한다. 단, 하나의 생성자라도 있으면 기본 생성자를 자동으로 제공하지 않는다.

사용자 정의 생성자

매개변수를 받아 객체의 필드를 초기화하는 생성자이다. 사용자 정의 생성자를 만들어놓으면, 이가 기본 생성자의 역할을 하고, 기본 생성자를 따로 만들고 싶으면 오버로딩을 통해 따로 정의해야 한다.

new

인스턴스(instance)를 생성하기 위해서 new 키워드를 사용하여 클래스의 생성자를 호출한다.

this

  • 자바에서 객체 자신을 참조하는 키워드
  • 클래스의 인스턴스 메서드나 생성자 내에서 객체 자신의 참조를 제공한다.

생성자 체이닝 (Constructor Chaining)

this는 같은 클래스의 다른 생성자를 호출할 때도 사용한다. 이를 통해 코드 중복을 줄이고 생성자의 초기화를 통합할 수 있다.

public class A {
	private int b;
    private int c;
    
    public A() {
    	this(0,0); // 다른 생성자를 호출
    }
    
    public A(int b, int c) {
    	this.b = width;
        this.c = height;
    }
}

메서드 체이닝 (Method Chaining)

메서드가 this를 반환하여 연속적으로 메서드를 호출할 수 있게 하는 패턴

스코프 (Scope)

  • 변수와 메소드가 유효하고 접근 가능한 범위를 정의하는 개념
  • 변수가 선언된 위치에 따라 달라지는 유효 범위를 의미

static

  • 클래스 수준에서 멤버를 정의할 때 사용
  • 인스턴스와는 독립적으로 메모리에 할당되고 모든 인스턴스가 공유하는 특성이 있다.
  • 클래스 로딩 시 메모리에 할당된다.
public class AClass {
	private int instanceVar;
    private static int staticVar;
    
    public void instanceMethod() {
    	// 인스턴스 변수와 정적 변수 모두 접근 가능
        instanceVar = 10;
        staticVar = 20;
    }
    
    public static void staticMethod() {
    	// 정적 변수만 접근 가능
        staticVar = 30;
        // instanceVar는 접근 불가능
    }
}
  • 정적변수(static 변수)는 클래스가 메모리에 올라갈 때, 메모리에 할당되며, 클래스의 모든 인스턴스에서 공유된다.
  • static이 붙으면, 클래스 멤버 변수라고 부른다.
  • static이 안 붙으면 인스턴스화 할 때 살아난다.
  • 인스턴스 변수는 클래스의 인스턴스가 생성될 때 메모리에 할당되며, 클래스의 모든 메서드에서 접근할 수 있다.
public static void main(String[] args) {
	Myclass instance1 = new MyClass(); 
    Myclass instance2 = new MyClass(); 
    Myclass instance3 = new MyClass(); 
    
    instance1.instanceMethod(50); // staticField = 40, fieldA = 50
    instance2.instanceMethod(30); // staticField = 40, fieldA = 30
    
    Myclass.staticMethod(40); // staticField = 40, fieldA = 50
    // 클래스에서 공유하는 변수, Myclass에 있는 static 변수의 값이 바뀐 것
}

상속과 인터페이스

상속 (Inheritance)

  • 기존 클래스(부모 클래스, 슈퍼 클래스)의 속성과 메소드를 새로운 클래스(자식 클래스, 서브 클래스)에게 물려줘서 사용할 수 있게 하는 것
  • 상속을 통해 자식 클래스는 부모 클래스에서 정의된 모든 속성과 메서드를 그대로 사용할 수 있으며, 필요한 경우 이를 확장하거나 재정의(오버라이딩) 할 수 있다.
  • 상위 클래스(Super Class), 부모 클래스(Parent Class), 기초 클래스(Basic Class)
  • 하위 클래스(Sub Class), 자식 클래스(Child Class), 파생 클래스(Derived Class)

단일 상속 (Single Inheritance)

한 클래스가 단 하나의 상위 클래스로부터 상속을 받는 방식

  • 자바에서는 명시적으로는 단일 상속만 지원한다.
  • keyword extends를 사용한다.
  • 한 클래스는 하나의 부모 클래스만 상속받을 수 있다.
  • 상속구조가 명확하고 단순하게 유지하기 위해 단일 상속만 지원한다.
  • 하지만, 다른 방법을 이용하여 아래의 나머지 상속도 구현할 수 있다.

다중 상속 (Multiple Inheritance)

한 클래스가 두 개 이상의 상위 클래스로부터 상속을 받는 방식

  • 자바에서는 다중 상속의 문제를 해결하기 위해 인터페이스를 사용하여 유사한 기능을 제공한다.

계층적 상속 (Hiearchical Inheritance)

여러 하위 클래스가 하나의 상위 클래스를 상속받는 방식이다. 하나의 부모클래스가 여러 자식 클래스를 가질 수 있다.

  • A라는 클래스를 상속받은 A', B', C' 클래스들은 독립적으로 존재할 수 있다.

다층적 상속 (Multilevel Inheritance)

상속이 여러 단계로 이어지는 방식이다. 한 클래스가 다른 클래스의 하위 클래스가 되고 다시 상위클래스가 되는 형태이다.

하이브리드 상속 (Hybrid Inheritance)

여러 종류의 상속기법을 결합하여 사용하는 방식이다. 이전의 상속 패턴들을 조합하여 복잡한 상속구조를 형성한다.

extends

class 클래스 이름 extends 부모클래스 이름 {

}

Override

  • 부모 클래스에서 상속받은 메서드를 자식 클래스에서 재정의하는 것
  • 오버라이딩을 통해 자식 클래스는 부모 클래스의 기본 동작을 자신만의 방식으로 수정할 수 있고, 이를 통해 다형성을 구현한다.
class Dog {
	public void bark(int times) {
    	for(int i=0;i<times;i++){
        	System.out.println("멍!");
        }
    }
}

class Husky extends Dog {
	@Override
    public void bark(int times) {
    	for(int i=0;i<times;i++){
        	System.out.println("멍!");
            System.out.println("멍!");
        }
    }
}

접근제어자 일치

Override된 메서드는 부모 클래스보다 더 제한적일 수 없다.

  • 부모 클래스 : public -> 자식 클래스 : public (가능)
  • 부모 클래스 : protected -> 자식 클래스 : public (가능)
  • 부모 클래스 : protected -> 자식 클래스 : private (불가능)

메서드 시그니처 일치

Override된 메서드는 원본 메서드와 시그니처가 일치해야 한다.
메서드 이름, 메서드 매개변수 리스트, 반환 타입이 동일하야 한다. 그렇지 않을 경우, 오버로딩이 된다.

예외처리 일치

Override된 메서드는 원본메서드와 예외처리가 일치해야 한다.

super

super 키워드는 하위 클래스에서 상위 클래스를 가리킬 때 사용한다. 상속 관계에서 자식 클래스가 부모 클래스의 기능을 참조하거나 호출할 때 사용한다.

class Husky extends Dog {
	
    public Husky(String name) {
    	super(name);
    } # 자식 클래스의 생성자에서 super()를 호출하여 부모클래스의 생성자를 호출할 수 있으며, 이를 통해 부모 클래스의 필드를 초기화하거나 기본 설정을 수행할 수 있다. 부모 클래스의 생성자는 super()를 사용하여 명식적으로 호출하지 않더라도 자식 클래스의 생성자가 호출될 때 자동으로 호출된다.
    
    @Override
    public void eat(String food) {
    	super.eat(food); # 부모 클래스 참조
        System.out.println("멍!");
    }
}

추상 클래스 (Abstract Class)

  • 클래스의 기본 형태를 정의하고, 이를 상속받아 구체적인 구현을 제공할 수 있도록 하는 클래스
  • 직접적으로 인스턴스화될 수 없으며, 다른 클래스가 이를 상속받아 구현을 완성해야 한다.
  • 상속을 통해 공통적인 기능을 제공하면서, 자식 클래스에서 구체적인 동작을 정의할 수 있는 기반을 마련한다.

추상 메서드 (Abstract Method)

Abstract Class는 추상 메서드(Abstract Method)를 하나 이상 보유할 수 있다. 추상 메서드는 메서드의 선언만 포함하며, 메서드 본체가 없다.

구현된 메서드

Abstract Class는 구현된 메서드도 보유할 수 있다. 이러한 일반 메서드는 자식 클래스에서 재정의(오버라이딩)할 필요 없이 그대로 사용할 수 있다.

인스턴스 생성 불가

Abstract Class는 직접 인스턴스로 생성하는 것이 불가능하다. 즉, new 키워드를 사용하여 추상 클래스의 객체를 생성할 수 없다. 추상 클래서는 오직 자식 클래스에서 구현된 다음에 생성하여 사용할 수 있다.

abstract

public abstract class Animal {
	
    public abstract void yelling();
    
    public void eat(int amount) {
    	System.out.println(amount + "만큼 먹었습니다. 배가 부릅니다.");
        
    }
    
    public void sleep(int hours){
    	System.out.println(hours + "만큼 낮잠을 잤습니다. 개운합니다.");
    }
}
  • 추상 클래스에는 일반 메서드 (구현된 메서드)와 추상 메서드(구현되지 않은 메서드) 모두를 포함할 수 있다.
  • 자식 클래스는 이 추상 메서드를 반드시 구현해야 하며, 그렇지 않으면 자식 클래스 또한 추상 클래스가 되어야 한다.

오늘 잘한점

오늘은 수업을 들으며 기록도 잘하고, 수업 내용도 놓치지 않고 잘 따라왔다. 그리고, 자율학습 시간 때 강의 자료를 쭉 다시 복습하면서 내가 놓친 부분, TIL에 더 기록할 부분, 이해가 되지 않는 부분을 뽑아낼 수 있었다. 강의 자료를 보고 이해가 되지 않는 부분을 바로 바로 강사님께 질문할 수 있어 더 이해하기 좋았던 것 같다 ! 수업을 듣고, 진짜 이해하고, 이것을 기록하는 것까지 어떻게 해야 할지 고민이 많았는데 하루하루 좀 나아지고 틀이 잡혀가는 것 같다.

오늘의 질문

Q. OOP 특징 중 추상화는 불필요한 구체적인 부분은 숨기고, 중요한 부분을 강조하여 보여주는 거라고 이해했습니다. 이를 abstract class와 interface로 구현할 때, (아직 interface는 안 배웠지만) 추상 메소드로 메소드 본체를 구현하지 않는 것이 불필요한 부분을 숨기는 거라고 할 수 있는 건가요? 아니면 자식 클래스에서 꼭 구현하게 함으로써 중요한 부분을 드러내서 강조한다고 이해해야 하나요

A. 추상 메서드로서 메서드를 구현하지 않고 두는 것은 불필요한 것을 숨긴다 라는 표현 보다는 해당 객체가 “무엇을 할 수 있는지”에 초점을 맞추어 정의해둔 다음에 이 클래스를 구현하는(상속받는)클래스는 반드시 해당 기능을 구현해야하는 것을 지정하기 위함이라고 보는것이 보다 적절할 수 있을 것 같습니다.

즉, 추상 메서드는 반드시 구형해야 하는 중요한 기능만을 보여주는 것이다로 이해할 수 있을 것 같습니다.

느낀 점

일주일이 끝났다. 고작.. 일주일이 끝났다. 하하하하 시작이 반이겠지? 꾸준히 열심히 하고 싶다. 지금은 힘들진 않는데, 지치지 않고 잘 끝낼 수 있길 바란다. 할수록 루틴이나 공부 계획이 잡히는 것 같아서 좋다. 그리고, 슬슬 내가 전공 수업에서 배우고 까먹은 내용들이 나오기 시작하는데 열심히 잘 들어두고 기록해서 이젠 까먹지 않도록 해야 할 것 같다. 1주차를 무사히 성공적으로 잘 해낸 나에게 박수 ~! 하루 하루 퀘스트 깨는 것처럼 하면 잘 되겠지 뭐~ !!
그리고, 6시 이후 시간에 어떻게 하면 생산적으로 시간을 보낼 수 있을지 고민해봐야겠다 ! 파이팅 ! :)

0개의 댓글