[Java] 객체지향 프로그래밍 (OOP)
by Frinee객체지향 프로그래밍 (OOP: Object-Oriented Programming)
: 실제 세계의 개념을 소프트웨어로 모델링하여 효율적이고 직관적인 프로그램을 개발할 수 있도록 하는 프로그램 패러다임
1. 클래스와 객체
클래스(Class)
- 클래스(Class)는 객체를 정의하는 틀 또는 설계도의 의미로 사용됨.
- 클래스는 속성 변수를 나타내는 필드(field)와 객체의 함수를 나타내는 메소드(method)로 구성됨.
public class Circle {
// 필드(field)
public int radius;
public String name;
// 메소드(method)
public Circle() { // 생성자 메소드
}
public double getArea() { // 원의 면적 메소드
return 3.14*radius*radius;
}
}
객체(Object)와 인스턴스(instance)
- 객체(Object): 물리적으로 존재하거나 개념적인 것 중에서 다른 것과 식별 가능한 것을 말함.
- 예를 들어 물리적으로 존재하는 자동차,자전거나 개념적인 학과, 강의 등이 모두 객체가 될 수 있음
- 인스턴스(instance): 클래스에 의해서 만들어진 객체를 의미함.
- 클래스가 어떤 데이터의 구조 설계도라면, 객체는 설계도를 이용해 찍어낸 실 데이터라고 보면 된다.
// 클래스
class Animal { ... }
public class Sample {
public static void main(String[] args) {
// 변수 cat은 객체
// 변수 catd은 Animal 클래스의 인스턴스
Animal cat = new Animal(); // 클래스라는 설계도를 통해 객체 데이터를 new 생성
}
}
필드(field)
- 클래스에 포함된 변수(variable)을 말한다.
- 클래스 멤버(member)라고도 불린다.
- 클래스 필드는 선언된 위치와 선언자에 따라 다음과 같이 구분됨.
- 클래스 변수(static variable)
- 인스턴스 변수(instance variable)
- 지역 변수(local variable)
class Field {
static int classVar = 10; // 클래스/스태틱 변수 선언
int instanceVar = 20; // 인스턴스 변수 선언
int method() {
int localVar = 30; // 지역 변수 선언
return localVar;
}
}
public class Member01 {
public static void main(String[] args) {
System.out.println( Field.classVar ); // 클래스/스태틱 변수 참조
Field myField1 = new Field(); // 인스턴스 생성
System.out.println( myField1.instanceVar ); // 인스턴스 변수 참조
System.out.println( myField1.method() ); // 메서드안의 지역변수 출력
}
}
변수 | 생성 시기 | 소멸 시기 | 저장 메모리 |
클래스 변수 | 클래스가 메모리에 올라갈 때 | 프로그램이 종료될 때 | 메소드 영역 |
인스턴스 변수 | 인스턴스가 생성될 때 | 인스턴스가 소멸할 때 | 힙 영역 |
지역 변수 | 블록 내에서 변수의 선언문이 실행될 때 | 블록을 벗어날 때 | 스택 영역 |
- 클래스 변수는 인스턴스를 생성하지 않아도 조회할 수 있다.
2. 메서드와 생성자
메서드(Method)
- 클래스 내에 구현된 함수를 말함.
- 다른 프로그래밍 언어에서는 함수(function)라는 개념을 자바에서는 메소드(method)라 표현함.
- 메서드 정의
- 접근 제어자/지정자: 해당 메서드에 접근할 수 있는 범위를 명시
- 반환 타입(return type): 메서드가 모든 작업을 마치고 반환하는 데이터 타입을 명시
- 메서드명: 메서드를 호출하기 위한 이름을 명시
- 매개변수 목록(parameters): 메서드 호출 시에 전달되는 인수의 값을 저장할 변수들을 명시
- 구현부: 메서드의 고유 기능을 수행하는 명령문의 집합. 중괄호 { } 안에 포함
생성자
- 객체가 생성될 때 동적으로 인스턴스 변수 초기화를 위해 실행되는 특수한 메서드
- 생성자 규칙
- 생성자의 목적은 객체 초기화
- 생성자 이름은 클래스 이름과 반드시 동일
- 생성자는 new를 통해 객체를 생성할 때, 객체당 한 번 호출
- 생성자는 객체가 생성될 때 반드시 호출됨.
- 생성자는 return 타입을 지정하지 않음
- 생성자는 여러 개 작성할 수 있음(Overloading)
class Car {
String modelName;
int modelYear;
String color;
int maxSpeed;
int currentSpeed;
// 생성자 (인스턴스 변수 값 초기화)
Car(String modelName, int modelYear, String color, int maxSpeed) {
this.modelName = modelName; // 메서드의 입력값으로 인스턴스 변수의 값을 지정
this.modelYear = modelYear;
this.color = color;
this.maxSpeed = maxSpeed;
this.currentSpeed = 0; // 입력값 없이 디폴트 초기화
}
String getModel() {
return this.modelYear + "년식 " + this.modelName + " " + this.color;
}
}
public class Main {
public static void main(String[] args) {
Car myCar1 = new Car("아반떼", 2016, "흰색", 250); // 생성자의 호출
Car myCar2 = new Car("제네시스", 2020, "검은색", 500); // 생성자의 호출
Car myCar3 = new Car("티코", 2003, "빨간색", 100); // 생성자의 호출
System.out.println(myCar1.getModel()); // 2016년식 아반떼 흰색
System.out.println(myCar2.getModel()); // 2020년식 제네시스 검은색
System.out.println(myCar3.getModel()); // 2003년식 티코 빨간색
}
}
- this 참조 변수
- 클래스 자기 자신을 뜻하는 키워드
- 해당 인스턴스의 주소를 가리키고 있어 자기 자신에 접근이 가능함.
- this() 메서드
- 생성자 내부에서 같은 클래스의 다른 생성자를 호출할 때 사용.
Car() { this("소나타", 2012, "검정색", 160); // 해당 아규먼트가 일치하는 다른 생성자를 호출함. }
- 생성자 내부에서 같은 클래스의 다른 생성자를 호출할 때 사용.
3. 접근 제어자와 캡슐화
접근 제어자(access modifier)
- 변수나 메서드의 사용 권한을 설정하기 위한 기능을 수행
- 접근 제어자 종류
- private: 해당 클래스 안에서만 접근 가능
- default: 접근 제어자를 별도로 설정하지 않으면 자동으로 설정되며 동일한 패키지 안에서만 접근 가능
- protected: 동일 패키지의 클래스 또는 해당 클래스를 상속받은 클래스에서만 접근이 가능
- public: 어떤 클래스에서도 접근 가능
캡슐화(Encapsulation)
- 데이터를 보호하기 위해 접근을 제한하고 외부와의 상호작용은 공개된 메서드(getter, setter)를 통해서만 이루어지도록 하는 객체지향 프로그래밍의 중요한 원칙
- 데이터 은닉: 중요한 데이터는 private으로 보호
- 인터페이스 제공: 데이터를 읽거나 수정할 때, public 메서드를 통해 제한적으로 접근 허용
- 데이터 무결성 보장: 직접 접근을 차단해 데이터를 의도치 않게 변경하지 않도록 보호
public class Student {
private String name; // private으로 데이터를 보호
private int age;
// Getter 메서드
public String getName() {
return name;
}
// Setter 메서드
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0) { // 데이터 무결성을 위한 조건 추가
this.age = age;
} else {
System.out.println("Invalid age!");
}
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.setName("Alice"); // setter를 통해 이름 설정
student.setAge(20); // setter를 통해 나이 설정
System.out.println(student.getName()); // "Alice"
System.out.println(student.getAge()); // 20
}
}
4. 상속과 다형성의 기초
상속(inheritance)
- 하위 클래스가 상위 클래스의 기능을 그대로 물려받는 기능
- 상속 기능을 이용하면 상위 클래스의 특징을 하위클래스에서 상속받아 코드의 중복 제거, 코드 재사용성 증대
- 상속 시 키워드 extends 사용
class Animal {
int teethCount;
int legCount;
int tailCount;
}
class Dog extends Animal { // 상속을 통해 중복 코드를 제거
void bark();
}
class Cat extends Animal { // 상속을 통해 중복 코드를 제거
void meow();
}
class Lion extends Animal { // 상속을 통해 중복 코드를 제거
void roar();
}
다형성 1 - 메서드 오버라이딩(Method Overriding)
- 상위 클래스의 메서드를 하위 클래스가 동일한 형태로 또다시 구현하는 행위
- 즉, 메서드 덮어쓰기라 할 수 있다.
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Dog extends Animal {
void sleep() {
System.out.println(this.name + " zzz");
}
}
class HouseDog extends Dog {
// 메서드 오버라이딩(method overriding)
void sleep() {
System.out.println(this.name + " zzz in house");
}
}
public class Sample {
public static void main(String[] args) {
HouseDog houseDog = new HouseDog();
houseDog.setName("happy");
houseDog.sleep(); // happy zzz in house 출력
}
}
다형성 2 - 메서드 오버로딩(Method Overloading)
- 동일한 이름의 메서드를 매개변수의 타입, 개수, 순서에 따라 여러 개 정의
- 반환 타입만 다른 경우 오버로딩이 가능하지 않고 컴파일 타임에 어떤 메서드를 호출할 지 결정됨.
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Dog extends Animal {
void sleep() {
System.out.println(this.name + " zzz");
}
}
class HouseDog extends Dog {
void sleep() {
System.out.println(this.name + " zzz in house");
}
// 메서드 오버로딩(Method Overloading)
void sleep(int hour) {
System.out.println(this.name + " zzz in house for " + hour + " hours");
}
}
public class Sample {
public static void main(String[] args) {
HouseDog houseDog = new HouseDog();
houseDog.setName("happy");
houseDog.sleep(); // happy zzz in house 출력
houseDog.sleep(3); // happy zzz in house for 3 hours 출력
}
}
'Backend > Java' 카테고리의 다른 글
[Java] Generics, Enum, Annotation (1) | 2025.02.18 |
---|---|
[Java] 예외 처리(exception handling) (0) | 2025.02.11 |
[Java] 컬렉션 프레임워크(Collections Framework) (1) | 2025.02.09 |
자바 기본 구조와 기본 문법 (0) | 2025.01.18 |
블로그의 정보
프리니의 코드저장소
Frinee