풀스택 개발자 과정 12일차

너구·2026년 5월 21일

풀스택 성장과정

목록 보기
12/79

setter 활용하기

person에 이름(name) 속성을 할당하는 setter를 정의하라.
그리고 setter에 이름이 유효한지 검사하는 로직을 추가하라.

class Person {
    // private: 클래스 내부에서만 접근 가능
    // name 변수에 직접 접근이 불가합니다
    private String name;

    // setter
    void setName(String name) {
        // 이름을 검증하는 로직
        if (name.length() > 3) {
            System.out.println("유효한 이름을 입력하세요");
            return; // 이름이 유효하지 않으면 값을 할당하지 않는다
        }
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person();

        // 외부에서 접근 불가
        // person.name = "j";

        person.setName("John Doe");
    }
}

privat String name;을 사용해 name 변수에 직접 접근하지 못하도록 만들었다.
외부에서는 person.name처럼 값을 바로 수정할 수 없게 된다.
그 다음 setName() 이라는 setter 메서드를 만들었다.
이 메서드는 이름을 저장하기 전에 조건을 검사한다.
if문을 사용해 이름 길이가 3글자를 초과하는지 검사하였다.
만약 조건에 맞지 않으면 "유효한 이름을 입력하세요"를 출력하고 return을 사용해 함수가 바로 종료되도록 만들었다.
반대로 조건을 통과하면 this.name = name;을 통해 객체 안의 변수에 값을 저장하게 된다.


캡슐화 예제 (1)

앞에 예제에서 배운 getter, setter를 조합해서 Person 클래스의 name을 대상으로 캡슐화를 구현하라.

class Person {
    private String name;

    String getNamae() {
        return name;
    }

    void setName(String name) {
        if (name.length() < 3) {
            return;
        }
        this.name = name;
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person();

        // 이름 설정하기
        person.setName("John Doe");

        // 이름 접근하기
        System.out.println(person.getNamae());
    }
    
}

getter와 setter를 사용해 객체의 데이터를 안전하게 관리하는 방법을 연습해보았다.
private을 사용해 외부에서 name 변수에 접근하지 못하게 만들었고, setName() setter메서드를 통해 이름을 저장하도록 작성하였다.
if문을 사용해 이름 길이가 3글자보다 짧으면 저장하지 않도록 만들었고, 반대로 조건을 통과하면 this.name = name;을 통해 객체 안의 변수에 값을 저장하게 된다.
그리고 getName() Getter 메서드를 사용해 저장된 이름을 반환하도록 작성하였다.
Main 함수에서는 setName()으로 이름을 저장하고, getName()을 사용해 이름을 출력하였다.

캡슐화 예제 (2)

앞에 예제에서 배운 getter, setter를 조합해서 Person 클래스의 age를 대상으로 캡슐화를 구현하라.
age 조건 -> 나이는 음수가 될 수 없음.

class Person {
    private int age;

    int getAge() {
        return age;
    }

    void setAge(int age) {
        if (age < 0) {
            System.out.println("유효하지 않은 나이입니다");
            return;
        }
        this.age = age;
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person();

        person.setAge(-30);

        System.out.println(person.getAge());
    }
    
}

위와 동일한 방법으로 작성하였다.


Null

객체가 비어있음(Null)을 의미하는 특별한 상수이다.
변수 초기화 과정, 함수가 연산의 결과가 없음을 나타낼 때 사용한다.


NPE (Null Pointer Exception)

Null 객체 사용을 시도하는 경우 발생하는 예외이다.
이를 방지하기 위해 사전에 객체가 null인지 확인해야 한다.


Null 검사 예제

Person 객체를 생성하고 null을 할당하라.
그리고 객체를 사용하기 전에 null인지 확인하는 코드를 작성하라.

class Person {
    void greeting() {
        System.out.println("Hello");
    }
}

public class Main {
    public static void main(String[] args) {
        
        // person이 비어있음
        Person person = null;

        // npe를 방지하기 위해 객체를 사용하기 전에 null인지 검사합니다.
        if (person != null) {
            
        }
        person.greeting();
    }
}

먼저 Person 클래스 안에 void greeting(); 메서드를 만들고 "Hello"를 출력하도록 작성하였다.
그 다음 Person person = null;을 사용해 객체를 비어있는 상태로 만들었다.
여기서 null은 객체가 아직 생성되지 않은 상태를 의미한다.
그 다음 if문을 사용해 객체가 존재하는지 검사하였다.
! = null의 의미는 null이 아닐 때로, 객체가 실제로 생성되어있을 때만 메서드를 실행하도록 검사하는 것이다.
현재 코드는 중괄호 밖에서 person.greeting();을 실행하고 있기 때문에 person이 null 상태라 오류가 발생한다.


상속 (Inheritance)

하위 클래스가 상위 클래스로부터 데이터를 전달받는 것을 의미한다.
상위 클래스를 부모(Parent), 하위 클래스를 자식(Child)이라고도 부른다.

상속 관계 표현하기 (1)

다음 상속 관계를 구현해보라.

Person(부모)
name: String
age: int
Greeting();: String

Strudent(자식)
grade: int

// 부모 클래스
class Person {
    String name;
    int age;

    void greeting() {
        System.out.println("hello");
    }
}

// 자식 클래스
class Student extends Person { // 상속: extends (확장)
    int grade;
}

public class Main {
    
}

먼저 부모 클래스인 Person 클래스를 만들었다.
String name; int age;를 사용해 이름과 나이를 저장할 변수를 선언하였고, void greeting() 메서드를 사용해 "hello"를 출력하도록 작성하였다.
그 다음 clss Student extends Person을 사용해 student 클래스가 Person 클래스를 상속받도록 만들었다.
여기서 extends는 부모 클래스의 기능을 물려받는다라는 의미이다.
즉 Student 클래스는 직접 작성하지 않아도 name, age, greeting()을 모두 사용할 수 있게 된다.
그리고 int age;를 추가해 학생만의 속성도 따로 정의하였다.

상속관계 표현하기 (2)

다음 상속 관계를 구현해보라.

Car(부모)
modelName: String
color: String
year: int
drive(): void

Ev(자식)
battaryCapacity: int

// 부모
class Car {
    String modelName;
    String color;
    int year;

    void dirve() {
        System.out.println("brrrrrrr");
    }
}

// 자식
class Ev extends Car {
    // 배터리 용량 추가
    int batteryCapacity;
}

public class Main {
    
}

위와 같은 방법으로 코드를 작성해보았다.


자식 인스턴스

자식 클래스로 생성한 객체를 의미한다.
자식 인스턴스는 부모 클래스의 기능도 함께 사용할 수 있다.

자식 인스턴스 생성 예제(1)

student 클래스의 인스턴스를 생성하고 속성을 정의하라

// 부모
class Person {
    String name;
    int age;

    void greeting() {
        System.out.println("hello");
    }
}

// 자식
class Student extends Person {
    int grade;
}

public class Main {
    public static void main(String[] args) {
        
        Student student = new Student();

        student.name = "John Doe";
        student.age = 20;
        student.grade = 3;

        System.out.println(student.name);
        System.out.println(student.age);
        System.out.println(student.grade);
        
        // 메서드
        student.greeting();
    }
}

먼저 부모 클래스인 Person을 만들었다.
이름과 나이를 저장할 변수를 선언하고 메서드를 활용해 "hello"를 출력하도록 작성하였다.
그다음 class Student extends Person을 사용해 student 클래스가 Person의 클래스를 상속받게 만들었다.
즉 Student 클래스는 부모 클래스의 name, age, greeting(); 기능을 그대로 사용할 수 있게 되었고 int grade;를 추가해 학년 정보를 저장할 수 있게 하였다.
main 함수에서는 Student student = new Student();를 사용해 자식 클래스의 객체를 생성하였다.
그 다음 student.name, age, grade를 사용해 값을 저장하였다.
여기서 name과 age는 부모 클래스에서 물려받은 변수이고 grade는 자식 클래스에서 추가한 변수이다.
그 다음 print를 통해 저장한 값들을 출력하고 student.greeting();을 사용해 메서드도 호출해보았다.

자식 인스턴스 생성 예제 (2)

Ev 클래스의 인스턴스를 생성하고 속성을 정의하라.

class Car {
    String modelName;
    String color;
    int year;

    void drive() {
        System.out.println("brrrrrrrrrrr");
    }
}

class Ev extends Car {
    int batteryCapacity;
}

public class Main {
    public static void main(String[] args) {
        
        Ev ev = new Ev();

        ev.modelName = "KIA";
        ev.color = "white";
        ev.year = 2026;

        System.out.println(ev.modelName);
        System.out.println(ev.color);
        System.out.println(ev.year);

        ev.drive();
    }
    
}

예제 1번과 동일하게 작성하였다.


오버라이딩 (Overrideing)

부모의 메서드를 자식이 재정의하는 것을 의미한다.
오버라이딩을 통해 상속을 유연하게 구현할 수 있다.

오버라이딩 예제 (1)

Person 클래스의 greeting 메서드를 Student에 맞게 오버라이딩하라.

// 부모
class Person {
    void greeting() {
        System.out.println("안녕하세요");
    }
}

// 자식
class Student extends Person {
    void greeting() {
        System.out.println("안녕하세요 저는 학생입니다");
    }
}

public class Main {
    public static void main(String[] args) {
        Student student = new Student();

        student.greeting();
    }
}

먼저 부모 클래스인 Persond 클래스에서 메서드를 만들고 "안녕하세요"를 출력하도록 작성하였다.
그 다음 자식 클레스인 Student를 사용해 Person 클래스를 상속받았다.
그리고 자식 클래스 안에서 같은 이름의 void greeting() 메서드를 다시 작성하였다.
부모클래스의 메서드를 자식 클래스에서 다시 정의한 것이다.
따라서 student.greeting();를 실행하면 부모 클래스의 greeting()dl 아니라 자식 zmf래스에서 새롭게 작성한 "안녕하세요 저는 학생입니다"가 실행된다

오버라이딩 예제 (2)

Car 클래스의 drive 메서드를 EV에 맞게 오버라이딩 하라.

class Car {
    void drive() {
        System.out.println("brrrrrrrr");
    }
}

class Ev extends Car {
    void drive() {
        System.out.println("Evrrrrrrrrr");
    }
}
public class Main {
    public static void main(String[] args) {
        Ev ev = new Ev();

        ev.drive();
    }
}

1번 예제와 동일하게 작성하였다.

부모 생성자(Super Constructor)

자식의 생성자는 부모 생성자를 호출한다.
만약 따로 작성하지 않으면 컴파일러가 자동으로 호출한다.

부모 생성자 예제 (1)

Person, Studenet 클래스에 속성값을 할당하는 생성자를 추가하라.

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person {
    int grade;

    Student(String name, int age, int grade) {
        // super(): 부모 생성자
        // 물려받은 속성에 값을 할당할 때 부모 생성자 호출
        super(name, age);
        this.grade = grade;
    }
}

public class Main {
    public static void main(String[] args) {
        
        Student student = new Student("John Doe", 20, 3);
        
        System.out.println(student.name);
        System.out.println(student.age);
        System.out.println(student.grade);
    }
}

먼저 부모 클래스인 Person클래스를 만들고 이름과 나이를 저장할 변수를 선언하였다.
그리고 Person(String name, int age) 생성자를 사용해 전달받은 값을 객체 안에 저장하도록 하였다.
그 다음 class Student extends Person을 사용해 Student 클래스가 Person 클래스를 상속받도록 만들었다.
그리고 학생의 변수인 int grade;를 추가하였다.
Strudent 생성자에서는 super(name, age);를 사용하였다.
super()는 부모 클래스의 생성자를 호출하는 문법이다.
즉 부모 클래스에서 물려받은 name, age 값을 부모 생성자를 통해 초기화하도록 만든 것이다.
그리고 this.grade = grade;를 사용해 자식 클래스의 변수도 저장하였다.
main 함수에서는 new Student("John Doe', 20m 3)을 통해 이름, 나이, 학년 값을 한 번에 전달하며 객체를 생성하였다.
마지막으로 student.name, student.age, student.grade 를 출력해 저장된 값을 확인하였다.

부모 생성자 예제 (2)

Car, Ev 클래스에 속성값을 할당하는 생성자를 추가하라

class Car {
    String name;
    String color;
    int year;

    Car(String name, String color, int year) {
        this.name = name;
        this.color = color;
        this.year = year;
    }
}

class Ev extends Car {
    Ev(String name, String color, int year) {
        super (name, color, year);
    }
}

public class Main {
    public static void main(String[] args) {
        
        Ev ev = new Ev("벤츠", "검정", 2025);

        System.out.println(ev.name);
        System.out.println(ev.color);
        System.out.println(ev.year);
    }
    
}

1번 예제와 동일하게 작성하였다.


마무리

오늘은 상속과 부모 생성자, 오버라이딩 같은 객체지향 개념들을 배워보았다.
특히 상속을 사용하면 부모 클래스의 기능을 그대로 물려받아 사용할 수 있다는 점이 신기하고 흥미로웠다.

또 오버라이딩을 통해 같은 메서드라도 자식 클래스에서 원하는 방식으로 다시 정의할 수 있다는 점도 인상 깊었다.
캡슐화와 private, Getter/Setter를 배우면서 객체의 데이터를 안전하게 관리하는 이유도 조금씩 이해하게 되었다.

아직은 어렵고 헷갈리는 부분도 많지만, 직접 코드를 계속 작성해보면서 점점 익숙해지고 있다는 느낌이 들었다.

0개의 댓글