개발자교육
24_08_01 오늘의 수업내용
regnator
2024. 8. 1. 17:01
728x90
반응형
클래스와 객체
1. 클래스
- 개념: 클래스는 객체를 생성하기 위한 청사진 또는 설계도. 객체 지향 프로그래밍(OOP)에서 클래스는 데이터(필드)와 메서드(함수)를 하나로 묶어놓은 구조를 정의한다. 클래스는 객체를 생성하는 데 필요한 속성과 행동을 정의하며, 이 속성과 행동은 필드와 메서드로 구체화된다.
- 예시:
class Car {
// 필드(속성)
String model;
int year;
// 메서드(동작)
void drive() {
System.out.println("Driving...");
}
}
- 위의 Car 클래스는 자동차의 model과 year라는 속성을 정의하고, drive()라는 메서드를 통해 자동차가 "Driving..."이라는 메시지를 출력하는 동작을 정의.
2. 객체
- 개념: 객체는 클래스의 인스턴스입니다. 객체는 물리적이거나 개념적으로 존재하며, 클래스에 정의된 속성과 동작을 가진 실체이다. 객체는 클래스에 정의된 속성 값을 저장하고, 해당 속성에 따라 동작할 수 있다.
- 예시:
Car myCar = new Car(); // Car 클래스의 객체 생성
myCar.model = "Tesla"; // 객체의 필드에 값 할당
myCar.drive(); // 객체의 메서드 호출 -> "Driving..." 출력
- myCar는 Car 클래스의 인스턴스로, model 필드에 "Tesla"를 저장하고, drive() 메서드를 호출하여 동작을 수행한다.
객체 지향 프로그래밍의 특징
1. 캡슐화
- 개념: 캡슐화는 객체의 데이터(필드)와 메서드를 하나로 묶고, 외부에서는 객체의 내부 구현을 숨기는 원리다. 이를 통해 객체의 내부 상태를 보호하고, 외부에서 객체의 데이터를 직접 수정하는 것을 방지할 수 있다. 일반적으로 필드를 private으로 선언하고, 이를 읽고 수정하는 메서드(getter, setter)를 public으로 제공하여 외부에서 간접적으로 접근하도록 한다.
- 예시:
class Car {
private String model; // 필드를 private으로 선언하여 외부 접근을 제한
// public 접근자 메서드(getter)
public String getModel() {
return model;
}
// public 설정자 메서드(setter)
public void setModel(String model) {
this.model = model;
}
}
- 위의 코드에서 model 필드는 private으로 선언되어 외부에서 직접 접근할 수 없으며, getModel()과 setModel() 메서드를 통해 간접적으로 접근할 수 있다. 이를 통해 객체의 내부 데이터가 외부의 잘못된 접근으로부터 보호된다.
2. 상속
- 개념: 상속은 기존 클래스를 확장하여 새로운 클래스를 만드는 기능이다. 부모 클래스의 필드와 메서드를 자식 클래스가 물려받아 사용할 수 있다. 상속을 통해 코드의 재사용성을 높이고, 새로운 클래스에서 기존 클래스를 확장하거나 수정하여 새로운 기능을 추가할 수 있다.
- 장점:
- 코드 재사용성: 공통적인 기능을 부모 클래스에 정의하고, 자식 클래스에서 이를 재사용함으로써 중복 코드를 줄일 수 있다.
- 유지보수성 향상: 공통 코드가 부모 클래스에 집중되어 있어, 코드 변경이 필요할 때 부모 클래스만 수정하면 모든 자식 클래스에 적용.
- 예시:
class Vehicle {
String brand = "Ford";
void honk() {
System.out.println("Honk! Honk!");
}
}
class Car extends Vehicle {
String model = "Mustang";
void drive() {
System.out.println("Driving...");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.honk(); // "Honk! Honk!" 출력 (부모 클래스의 메서드)
System.out.println(myCar.brand + " " + myCar.model); // "Ford Mustang" 출력
}
}
- Car 클래스는 Vehicle 클래스를 상속받아 honk() 메서드와 brand 필드를 사용할 수 있다. 이를 통해 코드의 재사용성을 높이고, Car 클래스에서 추가적인 기능(drive() 메서드)을 정의할 수 있다.
3. 다형성
- 개념: 다형성은 동일한 메서드 호출이지만, 객체에 따라 다르게 동작하는 성질을 의미. 자바에서 다형성은 주로 메서드 오버로딩과 메서드 오버라이딩을 통해 구현. 다형성을 통해 코드의 유연성과 확장성을 높일 수 있다.
- 오버로딩:
- 개념: 같은 이름의 메서드를 여러 번 정의하되, 매개변수의 타입이나 개수를 다르게 하여 사용하는 것.
예시:
class MathOperations {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
MathOperations math = new MathOperations();
System.out.println(math.add(2, 3)); // 5 출력
System.out.println(math.add(2.5, 3.5)); // 6.0 출력
System.out.println(math.add(1, 2, 3)); // 6 출력
}
}
- add 메서드는 매개변수의 타입과 개수에 따라 여러 버전이 존재한다. 이처럼 같은 이름의 메서드를 여러 개 정의하는 것이 오버로딩이다.
- 오버라이딩:
- 개념: 부모 클래스에서 정의된 메서드를 자식 클래스에서 재정의하여 사용하는 것. 오버라이딩된 메서드는 부모 클래스의 메서드와 동일한 이름, 매개변수, 반환 타입을 가져야 한다. 이를 통해 자식 클래스는 부모 클래스의 메서드를 재정의하여 필요에 맞게 동작을 변경할 수 있다.
- 예시:
class Animal {
void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.sound(); // "Bark" 출력
myCat.sound(); // "Meow" 출력
}
}
- Dog와 Cat 클래스는 Animal 클래스의 sound() 메서드를 오버라이딩하여 각기 다른 소리를 내도록 재정의했다. 다형성 덕분에 부모 타입인 Animal로 선언된 객체도 실제 객체에 따라 다른 동작을 수행할 수 있다.
추상화
- 개념: 추상화는 복잡한 시스템에서 핵심적인 기능이나 속성만을 추려내어 모델링하는 과정. 추상화를 통해 불필요한 세부사항을 감추고, 필요한 부분만을 강조하여 개발자가 개념적으로 이해하기 쉽게 한다. 자바에서는 추상 클래스와 인터페이스를 사용하여 추상화를 구현할 수 있다.
- 예시:
abstract class Animal {
abstract void sound(); // 추상 메서드
}
class Dog extends Animal {
void sound() {
System.out.println("Bark");
}
}
- Animal 클래스는 추상 클래스로, 구체적인 구현이 없는 추상 메서드를 포함한다. 이 메서드는 자식 클래스에서 구체적으로 구현된다. 이를 통해 공통된 기능을 추상화하고, 세부 구현은 자식 클래스에 맡길 수 있다.
접근제한자
- public: 모든 클래스에서 접근 가능. 다른 패키지에서도 접근할 수 있음.
- protected: 동일 패키지 내 또는 자식 클래스에서 접근 가능. 자식 클래스는 다른 패키지에 있더라도 접근 가능.
- (default): 접근 제한자를 명시하지 않으면 기본 접근 제한자로 설정되며, 동일 패키지 내에서만 접근 가능.
- private: 해당 클래스 내에서만 접근 가능. 외부 클래스나 자식 클래스에서는 접근할 수 없음.
클래스의 구성 멤버
1. 필드
- 개념: 필드는 객체의 상태를 저장하는 변수. 필드는 클래스 내에서 선언되며, 객체가 생성될 때 초기화된다. 필드는 객체의 속성값을 저장하며, 각 객체마다 고유의 필드 값을 가진다.
- 예시:
class Car {
String model; // 자동차 모델명
int year; // 제조 연도
}
2. 생성자
- 개념: 생성자는 객체가 생성될 때 호출되어 객체의 초기화를 담당하는 메서드. 생성자는 클래스와 동일한 이름을 가지며, 반환 타입이 없다. 생성자는 객체 생성 시 필요한 초기값을 설정하는 데 사용.
- 예시: 생성자를 통해 Car 객체를 생성할 때 model과 year 값을 초기화할 수 있다.
class Car {
String model;
int year;
Car(String model, int year) { // 생성자 선언
this.model = model;
this.year = year;
}
}
- 기본 생성자: 생성자를 정의하지 않으면 자바 컴파일러가 자동으로 매개변수가 없는 기본 생성자를 제공.
3. 메서드
- 개념: 메서드는 객체의 동작을 정의하는 코드 블록. 메서드는 호출되면 특정 작업을 수행하며, 객체의 상태를 변경하거나 특정 기능을 수행할 수 있다. 메서드는 입력값(매개변수)을 받아 처리하고, 결과를 반환할 수 있다.
- 예시:
class Car {
void drive() { // 메서드 선언
System.out.println("Driving...");
}
}
- drive() 메서드는 호출되면 "Driving..."이라는 메시지를 출력하는 기능을 수행
필드 초기화와 사용
- 초기화: 필드는 객체가 생성될 때 기본값으로 초기화되며, 명시적으로 값을 할당할 수 있다. 예를 들어, 숫자 타입 필드는 0으로, 참조 타입 필드는 null로 초기화.
- 사용: 객체가 생성된 후, 필드에 접근하여 값을 읽거나 쓸 수 있다.
Car myCar = new Car("Tesla", 2020); // 생성자를 통한 필드 초기화
System.out.println(myCar.model); // "Tesla" 출력
가변 길이 매개변수와 리턴
- 가변 길이 매개변수: 메서드가 호출될 때 몇 개의 인수가 전달될지 미리 알 수 없는 경우, 가변 길이 매개변수를 사용하여 다양한 수의 인수를 처리할 수 있다.
void printNumbers(int... numbers) {
for (int number : numbers) {
System.out.println(number);
}
}
- printNumbers 메서드는 여러 개의 정수를 매개변수로 받아 출력한다.
- 리턴: 메서드는 연산 결과나 처리된 데이터를 호출한 곳으로 반환할 수 있다. void 는 반환값이 없음을 의미한다
int add(int a, int b) {
return a + b;
}
조건문을 활용한 에러 처리
- 조건문: 조건에 따라 코드의 실행 흐름을 제어할 수 있다. 예를 들어, 특정 조건이 만족되지 않으면 예외를 발생시켜 에러를 처리할 수 있다.
- 예시:
int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Divisor cannot be zero");
}
return a / b;
}
- divide 메서드는 두 수를 나누지만, 분모가 0일 경우 IllegalArgumentException을 던져 에러를 처리.
728x90
반응형