[ 3주차 - 0826 ]
금일 커리큘럼
├ 09:00 ~ 12:00 자바 프로그래밍 기초 (객체 형변환, 추상 클래스)
└ 13:00 ~ 18:00 자바 프로그래밍 기초 (인터페이스, 디자인 패턴, 오브젝트, 개념정리)
1. 객체 형변환
- 상속 관계에서 부모 타입 변수로 자식 객체를 참조하거나,
자식 타입으로 명시적 형변환하는 것 - 자바에서는 부모 타입 변수로 자식 객체를 참조할 수 있지만,
자식 타입의 멤버를 사용하려면 명시적 형변환이 필요함
간단한 예시
Parent c = new Child(); // 묵시적 형변환 (자동)
((Child)c).method(); // 명시적 형변환 (자식타입으로 변경 후 메서드 실행)
객체 형변환 예시
class Parent {
int num = 5;
public int getNum() {
return num;
}
}
class Child extends Parent {
int num = 10;
@Override
public int getNum() {
return num;
}
public void print() {
System.out.println(num);
}
}
public class Exam {
public static void test(Parent p) {
System.out.println(p.num);
System.out.println(p.getNum());
// 명시적 형변환
if (p instanceof Child) {
((Child)p).print();
}
}
public static void main(String[] args) {
Parent p = new Parent();
System.out.println(p.num); // 5
System.out.println(p.getNum()); // 5
Child c = new Child();
System.out.println(c.num); // 10
System.out.println(c.getNum()); // 10
c.print(); // 10
// 묵시적 형변환
Parent pc = new Child();
System.out.println(pc.num); // 5
System.out.println(pc.getNum()); // 10
// 명시적 형변환
((Child)pc).print(); // 10
System.out.println("-".repeat(5));
test(p); // 5, 5
System.out.println("-".repeat(5));
test(c); // 5, 10, 10
System.out.println("-".repeat(5));
test(pc); // 5, 10, 10
}
}
2. 추상 클래스 (abstract)
- 추상 클래스는 상속을 통해 자식 클래스가 공통된 구조를 가질 수 있게 함
- 추상 클래스는
abstract키워드를 사용하여 선언함public abstract class Animal {}
- 특정 기능을 추상 메서드로 선언하여 자식 클래스에서 반드시 구현하도록 일반화 함
public abstract void sound();- 특정 기능에 대해 마음대로 네이밍 정의 못하게 하고 일관성 유지하는 특징이 있음
- 추상 클래스는 객체 생성 안됨
Animal aa = new Animal(); // 불가
활용 예시
// 부모 추상 클래스
// Animal.java
public abstract class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public abstract void info(); // 추상 메서드
public abstract void sound(); // 추상 메서드
}
Animal{}클래스는 추상 클래스이며,sound()와info()는 추상 메서드
// 자식 클래스 - 1
// Dog.java
public class Dog extends Animal {
public Dog(String name, int age) {
super(name, age);
}
@Override
public void info() {
System.out.println("강아지\n이름: " + getName() + ", 나이: " + getAge());
}
@Override
public void sound() {
System.out.println("멍멍!");
}
}
// 자식 클래스 - 2
// Cat.java
public class Cat extends Animal {
public Cat(String name, int age) {
super(name, age);
}
@Override
public void info() {
System.out.println("고양이\n이름: " + getName() + ", 나이: " + getAge());
}
@Override
public void sound() {
System.out.println("야옹~");
}
}
- 부모 추상클래스의
abstract메서드를 오버라이딩해서 구현 필수
// 사용
// import animal.Animal;
import animal.Dog;
import animal.Cat;
public class Exam {
public static void main(String[] args) {
Dog dog = new Dog("초코", 12);
Cat cat = new Cat("춘삼", 11);
dog.info();
dog.sound();
System.out.println("-".repeat(5));
cat.info();
cat.sound();
}
}
# 실행 결과
고양이
이름: 춘삼, 나이: 11
야옹~
-----
강아지
이름: 초코, 나이: 12
멍멍!
3. 인터페이스 클래스 (interface)
- 인터페이스는 껍데기 형식 - 구현 형태가 없는 것이 기본임
- 내부 메서드는 추상클래스로 자동 설정됨
- 네이밍 규칙은
파스칼 표기법(PascalCase)따름 - 기존 일반 상속은 1개만 되는 단일 상속이지만, 인터페이스 타입은 다중 상속 가능함
- 선언 방식 (interface - implements)
- 부모1 :
public interface 부모1 {} - 부모2 :
public interface 부모2 {} - 자식 :
public class 자식 implements 부모1, 부모2 {}
- 부모1 :
- 인터페이스 끼리 상속 방식 (interface - extends)
- 인터1 :
public interface 인터1 {} - 인터2 :
public interface 인터2 {} - 인터3 :
public interface 인터3 extends 인터1, 인터2 {}
- 인터1 :
활용 예시
// path : _interface/InterA.java
package _interface;
public interface InterA {
void draw(); // 추상메서드 (자동)
void erase();
}
// path : _interface/InterB.java
package _interface;
public interface InterB {
void resize(double factor);
}
// path : _interface/Photo.java
package _interface;
public class Photo implements InterA, InterB {
private String fileName;
private int width, height;
public Photo(String fileName, int width, int height) {
this.fileName = fileName;
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println(fileName + " 사진을 화면에 그립니다.");
}
@Override
public void erase() {
System.out.println(fileName + " 사진을 화면에서 지웁니다.");
}
@Override
public void resize(double factor) {
width = (int)(width * factor);
height = (int)(height * factor);
System.out.println("크기 조정: " + width + "x" + height);
}
}
// path : ./InterExam.java
import _interface.InterA;
import _interface.InterB;
import _interface.Photo;
public class InterExam {
public static void main(String[] args) {
double fa = 2.5;
// 인터페이스도 타입으로 사용 가능
InterA fileA = new Photo("fileA.png", 200, 300);
fileA.draw();
fileA.erase();
// fileA.resize(fa); // 불가
((Photo)fileA).resize(fa); // 명시 변환 후 사용
((InterB)fileA).resize(fa); // 명시 변환 후 사용
System.out.println("-".repeat(5));
InterB fileB = new Photo("fileB.png", 100, 200);
((InterA)fileB).draw();
((Photo)fileB).erase();
fileB.resize(fa);
System.out.println("-".repeat(5));
Photo photo = new Photo("photo.png", 50, 50);
photo.draw();
photo.erase();
photo.resize(fa);
}
}
# 실행 결과
fileA.png 사진을 화면에 그립니다.
fileA.png 사진을 화면에서 지웁니다.
크기 조정: 500x750
크기 조정: 1250x1875
-----
fileB.png 사진을 화면에 그립니다.
fileB.png 사진을 화면에서 지웁니다.
크기 조정: 250x500
-----
photo.png 사진을 화면에 그립니다.
photo.png 사진을 화면에서 지웁니다.
크기 조정: 125x125
인터페이스의 default와 static 메소드
인터페이스에 기능메서드 추가되면 구현한클래스들 전부 수정해야 되는 단점이 있으나 default, static 형태로 추가 메서드 제공 가능하다. (JDK 8+)
- 인터페이스의 default 메서드
- 추가 오버라이딩이 필요한 기능메서드인 경우 사용
- 인터페이스의 static 메서드
- 구현한클래스(자식)에 없어도 사용할 수 있게 직접 호출 방식
- static이라서 형 변환해서 사용 못하니 참고
- ✅
InterC.infoVersion();가능 - ❌
((InterC)test2).infoVersion();불가능
- ✅
TIP
static 메서드는 클래스(또는 인터페이스) 자체에 속하며, 객체(인스턴스)에 속하지 않음
static 메서드는 반드시 타입명(클래스명/인터페이스명).메서드명()으로 호출
static 메서드는 오버라이딩도 불가능하며, 항상 선언된 타입의 메서드가 호출됨
public interface InterC {
void cMethod1();
void cMethod2();
default void cMethod3(); // 메서드 추가
static void infoVersion() {
System.out.println("버전 : v1.10");
}
}
// other file 1...
public class Test1 implements InterC {
@Override
void cMethod1() {
System.out.println("Test1 - cMethod1");
}
@Override
void cMethod2() {
System.out.println("Test1 - cMethod2");
}
// cMethod3 없어도 구현됨.
}
// other file 2...
public class Test2 implements InterC {
@Override
void cMethod1() {
System.out.println("Test2 - cMethod1");
}
@Override
void cMethod2() {
System.out.println("Test2 - cMethod2");
}
@Override
void cMethod3() {
System.out.println("Test2 - cMethod3");
}
}
// other file 3...
public class TestExam {
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.cMethod1();
test1.cMethod2();
Test2 test2 = new Test2();
test2.cMethod3();
InterC.infoVersion();
// ((InterC)test2).infoVersion(); // 불가
}
}
4. 디자인 패턴 (싱글,팩토리)
싱글톤 패턴
싱글톤 패턴은
getInstance()로 객체를 얻고, 항상 같은 인스턴스가 반환
// 싱글톤 클래스 정의
public class Singleton {
// 1. 클래스 내부에 static으로 유일한 인스턴스 변수 선언
private static Singleton instance;
private int count = 0; // 필드 변수
// 2. 생성자를 private으로 선언하여 외부에서 객체 생성 불가
private Singleton() {
// ...
}
// 3. public static 메서드로 인스턴스를 반환 (없으면 생성)
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void printMessage() {
System.out.println("싱글톤 객체입니다!");
}
public void addCount() {
count++;
}
public int getCount() {
return count;
}
}
// 사용 예제
public class Main {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
s1.printMessage();
// 두 객체가 같은지 확인
System.out.println(s1 == s2); // true
s1.addCount();
s2.addCount();
System.out.println(s1.getCount()); // 2
System.out.println(s2.getCount()); // 2 (같은 객체)
}
}
팩토리 메서드 패턴
팩토리 메서드 패턴은 객체 생성 로직을 별도의 팩토리 클래스에서 처리하여, 코드의 확장성과 유지보수를 높여줌.
// 제품 인터페이스
interface Animal {
void sound();
}
// 구체적인 제품 클래스
class Dog implements Animal {
public void sound() {
System.out.println("멍멍!");
}
}
class Cat implements Animal {
public void sound() {
System.out.println("야옹~");
}
}
// 팩토리 클래스
class AnimalFactory {
public static Animal createAnimal(String type) {
if (type.equals("dog")) {
return new Dog();
} else if (type.equals("cat")) {
return new Cat();
}
return null;
}
}
// 사용 예제
public class Main {
public static void main(String[] args) {
Animal a1 = AnimalFactory.createAnimal("dog");
Animal a2 = AnimalFactory.createAnimal("cat");
a1.sound(); // 멍멍!
a2.sound(); // 야옹~
}
}
5. 오브젝트 클래스 (object)
- 모든 클래스의 최상위 클래스
- 모든 객체가 공통으로 가져야 할 기본 메소드 제공 (toString, equals 등...)
extends없으면 오버라이딩 시 오브젝트 상속
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// toString() 오버라이딩
@Override
public String toString() {
return "Person = {name='" + name + "', age=" + age + "}";
}
}
public class ObjectTest {
public static void main(String[] args) {
Person p1 = new Person("홍길동", 55);
// toString() 테스트
System.out.println(p1.toString()); // Person = {name='홍길동', age=55}
System.out.println(p1.hashCode()); // Person@해시코드
// toString 오버라이딩을 안했다면 객체.투스트링은 해시코드로 나타남.
}
}
6. 개념 정리
접근 제한자
| 접근 제한자 | 같은 클래스 | 같은 패키지 | 자식 클래스 | 전체 |
|---|---|---|---|---|
| private | O | X | X | X |
| (default) | O | O | X | X |
| protected | O | O | O | X |
| public | O | O | O | O |
상속 금지 final 클래스
- 상속을 금지 시키려면 클래스를 정의할 때 final키워드를 사용
public final class 클래스명 { ...... }
타입확인 ( instanceof )
- 해당 타입이 어느 상속클래스 or 인터페이스 바라보고 있는지 확인하는 경우
Animal animal = new Dog();
if(animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.sound();
}
etc.
메서드 오버라이딩 금지 방식
- 템플릿 메서드 패턴
- 메서드 앞에
final붙게되면@Override로 해당 메서드 오버라이딩 할 수 없다.
public abstract class Game {
// 템플릿 메소드
// final -> 자식 클래스는 play() 해당 메서드 오버라이딩 금지됨.
public final void play() {
init();
start();
end();
}
// 추상 메소드들 (하위 클래스에서 구현)
abstract void init();
abstract void start();
abstract void end();
}
public class Chess extends Game {
@Override
void init() {
System.out.println("초기화");
}
@Override
void start() {
System.out.println("시작");
}
@Override
void end() {
System.out.println("종료");
}
}
멋사 부트캠프 개인학습 git : https://github.com/star1431/backend
'멋사 - 부트캠프 19기 : Java > Java' 카테고리의 다른 글
| (08.28) java 기초 - System 클래스, Wrapper 클래스, 컬렉션 프레임워크 : List, Set, Map (4) | 2025.08.28 |
|---|---|
| (08.27) java 기초 - 오브젝트 Override, final과 열거형, 내부클래스, String 클래스, 스트링빌더&버퍼, Math (2) | 2025.08.27 |
| (08.25) java 기초 - 상속, getter & setter, 오버라이딩 & 오버로딩, 다형성 (0) | 2025.08.25 |
| (08.22) java 기초 - 생성자, this, 메서드체이닝, 패키지, static (2) | 2025.08.25 |
| (08.21) java 기초 - 다차원배열, 객체지향, 클래스, 필드, 메서드 (1) | 2025.08.25 |