SMALL
package Class;
import java.text.DecimalFormat;
import java.util.InputMismatchException;
import java.util.Scanner;
// 하나의 java파일에 여러개의 클래스를 작성할 경우 반드시 하나의 public class가 존재해야한다.
//설계도 클래스
class Calcul {
void cal (int x, int y) {
System.out.println("사칙연산을 시작합니다");
}
}
//더하기
class Add extends Calcul{
@Override
void cal (int x, int y) {
System.out.println(x+"+"+y+"="+(x+y));
}
}
//빼기
class Sub extends Calcul{
@Override
void cal (int x, int y) {
System.out.println(x+"-"+y+"="+(x-y));
}
}
//곱하기
class Mul extends Calcul{
@Override
void cal (int x, int y) {
System.out.println(x+"*"+y+"="+(x*y));
}
}
//나누기
class Div extends Calcul{
@Override
void cal (int x, int y) {
if (y == 0) {
System.out.println("0으로 나눌 수 없습니다.");
return;
}
// 출력1
System.out.printf("%d / %d = %.2f\n", x, y, ((float) x / (float) y));
// 출력2
DecimalFormat df = new DecimalFormat("#,###.##");
double v = x / (double) y;
System.out.println(x + "/" + y + "=" + df.format(v));
}
}
public class C6_오버라이딩 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String op = null;
int x=0, y=0;
Calcul ct = new Calcul();
while(true) {
System.out.println("=====================");
System.out.println("입력폼 예시 : 숫자 + 숫자");
System.out.println("연산자종류 선택(+,-,*,/)>>");
try {
System.out.print("x>> ");
x = Integer.parseInt(sc.next());
System.out.print("op>> ");
op = sc.next();
System.out.print("y>> ");
y = Integer.parseInt(sc.next());
//다형성구현 - 오버라이딩구현
if(op.equals("+")) {
//업캐스팅
ct = new Add(); // 부모 = 자식
}else if(op.equals("-")) {
ct = new Sub();
}else if(op.equals("*")) {
ct = new Mul();
}else if(op.equals("/")) {
ct = new Div();
}else {
System.out.println("잘못 입력하셨습니다.");
continue;
}
ct.cal(x, y);
} catch (NumberFormatException e) {
System.out.println("숫자를 올바르게 입력해주세요.");
sc.nextLine(); // 버퍼 비우기
} catch (Exception e) {
System.out.println("오류가 발생했습니다: " + e.getMessage());
}
System.out.println("계속 하시겠습니까?(y/n)");
String answer = sc.next();
if(answer.equals("n")) {
sc.close();
System.out.println("프로그램을 종료합니다...");
break;
}
}
}
}
=====================
입력폼 예시 : 숫자 + 숫자
연산자종류 선택(+,-,*,/)>>
x>> 10
op>> /
y>> 5
10 / 5 = 2.00
10/5=2
계속 하시겠습니까?(y/n)
n
프로그램을 종료합니다...
package Class;
/*
car - move()
|
|
-----------------------------------------
| | | |
Bus Ambulance Tax ?
name name name name
move() move() move() move()
...() ...() ...() ...()
*/
public class C7_다형성실습 {
public static void main(String[] args) {
/*
1. 자동차 배열 4개를 만든다
2. 배열에 버스,엠뷸런스,택시,화차물 객체를 저장한다
* 업캐스팅해서 저장해 둔다
c = new Bus();
3. 확장 for를 활용해서
if(객체 instanceof 클래스) {
. 재정의한 메서드 실행
. 내것만의 메서드 실행
}
*/
}
}
package 상속;
import bak.EE;
//private
class AA{
private String name = "홍길동";
private int age = 30;
private void methodA() {
System.out.println("A클래스-methodA입니다");
System.out.println(name);
System.out.println(age);
methodB();
}
void methodB() {
System.out.println("A클래스-methodB입니다");
}
}
//default
class BB{
String name = "홍길동";
int age = 30;
void methodA() {
System.out.println("B클래스-methodA입니다");
System.out.println(name);
System.out.println(age);
methodB();
}
void methodB() {
System.out.println("B클래스-methodB입니다");
}
}
//protected
class CC{
protected String name = "홍길동";
protected int age = 30;
void methodA() {
System.out.println("C클래스-methodA입니다");
System.out.println(name);
System.out.println(age);
methodB();
}
void methodB() {
System.out.println("C클래스-methodB입니다");
}
}
//public
class DD{
}
public class Ext_3_접근제한자 {
public static void main(String[] args) {
//private
AA a = new AA();
//String name = a.name;
//int age = a.age;
//a.methodA();
//a.methodB();
//default
BB b = new BB();
String name1 = b.name;
int age = b.age;
b.methodA();
b.methodB();
//protected
CC c = new CC();
String name2 = c.name;
int age2 = age;
c.methodA();
c.methodB();
//private
EE e = new EE();
String name = e.name;
}
}
package bak;
import 상속.FF;
/*
설령 상속관계라 하더라도
패키지가 다르다면... protected이상으로 지정되어야 한다
*/
public class EE extends FF {
protected String address = "서울";
//int age = 40;
protected void methodE() {
System.out.println("E클래스 입니다");
String name = super.name; //부모의 멤버변수 - protected
int age = super.age; //부모의 멤버변수 - public
}
}
package 상속;
public class FF {
protected String name = "홍길동";
public int age = 30;
void methodA() {
System.out.println("F클래스-methodA입니다");
System.out.println(name);
System.out.println(age);
methodB();
}
void methodB() {
System.out.println("F클래스-methodB입니다");
}
}
추상 클래스란?
추상 클래스는 클래스 설계에서 **구체적으로 구현되지 않은 메서드(추상 메서드)**를 포함하는 클래스로, 하위 클래스에서 반드시 구현해야 할 메서드를 정의하는 데 사용됩니다. 추상 클래스는 설계도를 제공하면서도 일부 공통 기능은 구현할 수 있는 특징이 있습니다.
특징
- 추상 메서드 포함:
- 추상 메서드는 구현되지 않은 메서드로, 선언만 하고 내용(구현부)을 작성하지 않습니다.
- 하위 클래스에서 반드시 구현해야 합니다.
-
abstract class Shape { abstract void draw(); // 추상 메서드 }
- 객체 생성 불가:
- 추상 클래스 자체로는 객체를 생성할 수 없습니다.
- 반드시 하위 클래스에서 상속받아 구체적으로 구현한 후 객체를 생성해야 합니다.
- 일반 메서드와 변수 포함 가능:
- 추상 클래스는 일반 메서드나 변수를 포함할 수 있어, 공통 동작이나 데이터를 정의할 수 있습니다.
-
abstract class Animal { void eat() { System.out.println("This animal eats food."); } }
- 다형성 지원:
- 추상 클래스는 **다형성(Polymorphism)**을 활용하는 데 유용합니다.
- 동일한 타입(추상 클래스 참조 변수)으로 다양한 하위 클래스의 객체를 처리할 수 있습니다.
문법
추상 클래스 선언
abstract class 클래스명 {
// 추상 메서드
abstract 반환타입 메서드명(매개변수);
// 일반 메서드
반환타입 메서드명(매개변수) {
// 구현 내용
}
}
추상 클래스 상속 및 구현
abstract class Shape {
abstract void draw(); // 추상 메서드
}
class Circle extends Shape {
@Override
void draw() {
System.out.println("Draw a circle");
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Circle(); // 다형성
shape.draw(); // Draw a circle
}
}
추상 클래스 vs 인터페이스
특징 추상 클래스 인터페이스
목적 | 클래스 설계도와 기본 구현 제공 | 완전한 설계도 제공 |
메서드 | 추상 메서드 + 일반 메서드 포함 가능 | Java 8 이전: 추상 메서드만 포함 Java 8 이후: 디폴트 메서드, static 메서드 지원 |
다중 상속 | 다중 상속 불가능 | 다중 상속 가능 |
변수 | 일반 변수와 상수를 가질 수 있음 | 상수만 선언 가능 |
객체 생성 | 직접 생성 불가 | 직접 생성 불가 |
키워드 | abstract | interface |
추상 클래스 활용 예
// 추상 클래스: 동물
abstract class Animal {
abstract void sound(); // 추상 메서드
void eat() {
System.out.println("This animal eats food.");
}
}
// 하위 클래스: 개
class Dog extends Animal {
@Override
void sound() {
System.out.println("Woof Woof");
}
}
// 하위 클래스: 고양이
class Cat extends Animal {
@Override
void sound() {
System.out.println("Meow Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog(); // 다형성
dog.sound(); // Woof Woof
dog.eat(); // This animal eats food.
Animal cat = new Cat(); // 다형성
cat.sound(); // Meow Meow
cat.eat(); // This animal eats food.
}
}
추상 클래스의 장점
- 설계와 구현 분리:
- 공통적인 기능은 추상 클래스에서 구현하고, 세부 사항은 하위 클래스에서 구현.
- 유지보수 용이:
- 변경 시 공통 로직은 추상 클래스에서만 수정하면 되므로 유지보수가 간편.
- 다형성 활용:
- 동일한 추상 클래스 타입으로 다양한 객체를 처리 가능.
추상 클래스는 코드 재사용성과 유연성을 높이는 강력한 도구로, 설계 단계에서 큰 도움을 줍니다.
package 추상클래스;
abstract class 동물{
abstract void 걷기();
abstract void 울기();
abstract void 싸움();
}
class 강아지 extends 동물{
@Override
void 걷기() {
}
@Override
void 울기() {
}
@Override
void 싸움() {
}
}
class 고양이 extends 동물{
String name;
@Override
void 걷기() {
}
@Override
void 울기() {
}
@Override
void 싸움() {
}
}
class 병아리 extends 동물{
@Override
void 걷기() {
}
@Override
void 울기() {
}
@Override
void 싸움() {
}
}
public class Ab1_동물Ex {
public static void main(String[] args) {
강아지 진주 = new 강아지();
}
}
인터페이스란?
자바에서 **인터페이스(Interface)**는 클래스의 설계도를 제공하는 특별한 타입으로, **구현되지 않은 메서드(추상 메서드)**와 상수만 포함할 수 있습니다. 인터페이스는 다중 상속을 지원하며, 클래스 간의 계약(Contract) 역할을 합니다.
특징
- 추상 메서드와 상수만 포함(Java 7까지):
- 모든 메서드는 public abstract이며, 구현부가 없습니다.
- 모든 변수는 public static final(상수)로 선언됩니다.
- 선언 시 생략 가능하며, 자바가 자동으로 처리합니다.
- Java 8 이후 새로운 기능:
- 디폴트 메서드(default method):
- 구현부가 있는 메서드를 포함할 수 있습니다.
- 인터페이스의 하위 호환성을 유지하면서 기능 확장이 가능합니다.
- 정적 메서드(static method):
- 정적 메서드를 포함할 수 있습니다.
- 객체 생성 없이 인터페이스 이름으로 호출 가능합니다.
- 디폴트 메서드(default method):
- Java 9 이후 새로운 기능:
- private 메서드:
- 인터페이스 내에서 디폴트 메서드나 정적 메서드의 공통 로직을 처리하기 위해 사용됩니다.
- private 메서드:
- 다중 상속 가능:
- 인터페이스는 여러 개를 **구현(implement)**할 수 있습니다.
- 이를 통해 다중 상속 문제를 해결할 수 있습니다.
- 객체 생성 불가:
- 인터페이스는 객체를 생성할 수 없습니다.
- 구현한 클래스를 통해서만 사용할 수 있습니다.
문법
인터페이스 선언
public interface 인터페이스명 {
// 추상 메서드
void 메서드명();
// 디폴트 메서드 (Java 8+)
default void defaultMethod() {
System.out.println("This is a default method.");
}
// 정적 메서드 (Java 8+)
static void staticMethod() {
System.out.println("This is a static method.");
}
}
인터페이스 구현
- implements 키워드를 사용하여 구현.
public class 클래스명 implements 인터페이스명 {
@Override
public void 메서드명() {
// 메서드 구현
}
}
예제
기본 인터페이스
interface Animal {
void sound(); // 추상 메서드
default void eat() { // 디폴트 메서드
System.out.println("This animal eats food.");
}
static void info() { // 정적 메서드
System.out.println("This is an Animal interface.");
}
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("Woof Woof");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("Meow Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // Woof Woof
dog.eat(); // This animal eats food.
Animal cat = new Cat();
cat.sound(); // Meow Meow
cat.eat(); // This animal eats food.
Animal.info(); // This is an Animal interface.
}
}
다중 인터페이스 구현
다중 구현
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("The duck is flying.");
}
@Override
public void swim() {
System.out.println("The duck is swimming.");
}
}
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // The duck is flying.
duck.swim(); // The duck is swimming.
}
}
장점
- 다중 상속 지원:
- 여러 인터페이스를 구현하여 다양한 기능을 조합할 수 있습니다.
- 표준화된 설계 제공:
- 인터페이스를 통해 구현 클래스의 공통 동작을 정의하고 강제할 수 있습니다.
- 유연성 향상:
- 코드의 결합도를 낮추고 유연한 설계를 가능하게 합니다.
활용 예: 전략 패턴
인터페이스는 디자인 패턴(특히 전략 패턴) 구현 시 자주 사용됩니다.
interface Strategy {
void execute();
}
class ConcreteStrategyA implements Strategy {
@Override
public void execute() {
System.out.println("Strategy A executed.");
}
}
class ConcreteStrategyB implements Strategy {
@Override
public void execute() {
System.out.println("Strategy B executed.");
}
}
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
}
public class Main {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategyA());
context.executeStrategy(); // Strategy A executed.
context.setStrategy(new ConcreteStrategyB());
context.executeStrategy(); // Strategy B executed.
}
}
package 인터페이스;
public class RobotEx {
static void action(Robot r) {
if(r instanceof DanseRobot) {
((DanseRobot) r).dance();
}else if(r instanceof DrawRobot) {
((DrawRobot) r).draw();
}else {
((SingRobot) r).sing();
}
}
public static void main(String[] args) {
//부모를 담는 객체배열
Robot[] rb = new Robot[3];
//업캐스팅
rb[0] = new DanseRobot();
rb[1] = new DrawRobot();
rb[2] = new SingRobot();
//출력
for(Robot r:rb) {
action(r);
}
}
}
package 인터페이스;
public interface Robot {
}
class DanseRobot implements Robot{
void dance() {
System.out.println("춤을 춥니다");
}
}
class DrawRobot implements Robot{
void draw() {
System.out.println("그림을 그립니다");
}
}
class SingRobot implements Robot{
void sing() {
System.out.println("노래를 부릅니다");
}
}
package 인터페이스;
// 인터페이스 R
interface R {
void connect(); // 연결 메서드
}
// 인터페이스 T
interface T {
void disconnect(); // 연결 해제 메서드
}
// Speaker 인터페이스 (R과 T 상속)
public interface Speaker extends R, T {
void volumeUp(); // 볼륨 올리기
void volumeDown(); // 볼륨 내리기
}
// Tv 클래스
class Tv implements Speaker {
private int volume = 10; // 볼륨 초기값
@Override
public void volumeUp() {
if (volume < 100) {
volume++;
System.out.println("TV 볼륨 증가: " + volume);
} else {
System.out.println("TV 볼륨은 최대입니다.");
}
}
@Override
public void volumeDown() {
if (volume > 0) {
volume--;
System.out.println("TV 볼륨 감소: " + volume);
} else {
System.out.println("TV 볼륨은 최소입니다.");
}
}
@Override
public void connect() {
System.out.println("TV 연결되었습니다.");
}
@Override
public void disconnect() {
System.out.println("TV 연결 해제되었습니다.");
}
}
// Audio 클래스
class Audio implements Speaker {
private int volume = 15; // 볼륨 초기값
@Override
public void volumeUp() {
if (volume < 50) {
volume++;
System.out.println("오디오 볼륨 증가: " + volume);
} else {
System.out.println("오디오 볼륨은 최대입니다.");
}
}
@Override
public void volumeDown() {
if (volume > 0) {
volume--;
System.out.println("오디오 볼륨 감소: " + volume);
} else {
System.out.println("오디오 볼륨은 최소입니다.");
}
}
@Override
public void connect() {
System.out.println("오디오 연결되었습니다.");
}
@Override
public void disconnect() {
System.out.println("오디오 연결 해제되었습니다.");
}
}
// Phone 클래스
class Phone implements Speaker {
private int volume = 5; // 볼륨 초기값
@Override
public void volumeUp() {
if (volume < 20) {
volume++;
System.out.println("폰 볼륨 증가: " + volume);
} else {
System.out.println("폰 볼륨은 최대입니다.");
}
}
@Override
public void volumeDown() {
if (volume > 0) {
volume--;
System.out.println("폰 볼륨 감소: " + volume);
} else {
System.out.println("폰 볼륨은 최소입니다.");
}
}
@Override
public void connect() {
System.out.println("폰 연결되었습니다.");
}
@Override
public void disconnect() {
System.out.println("폰 연결 해제되었습니다.");
}
}
package 인터페이스;
public class SpeakerEx {
public static void main(String[] args) {
// 스피커 객체 배열 생성 및 초기화
Speaker[] speakers = new Speaker[3];
speakers[0] = new Tv(); // TV 객체
speakers[1] = new Audio(); // Audio 객체
speakers[2] = new Phone(); // Phone 객체
// 반복문으로 모든 객체의 volumeUp, volumeDown 실행
for (Speaker speaker : speakers) {
System.out.println("=== 스피커 동작 시작 ===");
speaker.connect(); // 연결
speaker.volumeUp(); // 볼륨 증가
speaker.volumeDown(); // 볼륨 감소
speaker.disconnect(); // 연결 해제
System.out.println("=== 스피커 동작 종료 ===\n");
}
}
}
중첩 클래스(Nested Class)란?
자바에서 **중첩 클래스(Nested Class)**는 하나의 클래스 내부에 정의된 또 다른 클래스를 의미합니다. 중첩 클래스는 외부 클래스와 강하게 연관되어 있으며, 주로 외부 클래스와의 관계를 표현하거나 특정 논리적 그룹화를 위해 사용됩니다.
중첩 클래스의 종류
- 정적 중첩 클래스 (Static Nested Class)
- 외부 클래스의 인스턴스 없이도 사용 가능한 클래스.
- 외부 클래스와의 관계가 약한 경우 적합.
- static 키워드로 선언.
- 정적 멤버(static variables, methods)를 가질 수 있음.
- 비정적 중첩 클래스 (Non-Static Nested Class, Inner Class)
- 외부 클래스의 인스턴스와 연관된 클래스.
- 외부 클래스의 멤버(필드, 메서드)에 쉽게 접근 가능.
- static 키워드 없이 선언.
- 지역 중첩 클래스 (Local Inner Class)
- 메서드 내부에 정의된 클래스.
- 메서드가 실행될 때만 사용 가능.
- 외부 클래스의 멤버와 메서드의 지역 변수(필요시 final)에 접근 가능.
- 익명 중첩 클래스 (Anonymous Inner Class)
- 이름이 없는 클래스.
- 주로 인터페이스나 추상 클래스를 구현하거나 상속받아 1회성으로 사용.
- 람다 표현식 이전에는 이벤트 리스너 등의 구현에 주로 사용됨.
정적 중첩 클래스 예제
class OuterClass {
static class StaticNestedClass {
void display() {
System.out.println("정적 중첩 클래스");
}
}
}
public class Main {
public static void main(String[] args) {
// 정적 중첩 클래스는 외부 클래스의 인스턴스 없이 객체 생성 가능
OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
nested.display(); // 정적 중첩 클래스
}
}
비정적 중첩 클래스 예제
class OuterClass {
class InnerClass {
void display() {
System.out.println("비정적 중첩 클래스");
}
}
}
public class Main {
public static void main(String[] args) {
// 비정적 중첩 클래스는 외부 클래스의 인스턴스가 필요
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display(); // 비정적 중첩 클래스
}
}
지역 중첩 클래스 예제
class OuterClass {
void outerMethod() {
// 메서드 내부에 클래스 정의
class LocalInnerClass {
void display() {
System.out.println("지역 중첩 클래스");
}
}
// 지역 중첩 클래스의 객체 생성
LocalInnerClass local = new LocalInnerClass();
local.display();
}
}
public class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.outerMethod(); // 지역 중첩 클래스
}
}
익명 중첩 클래스 예제
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
// 익명 중첩 클래스
Greeting greeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("익명 중첩 클래스");
}
};
greeting.sayHello(); // 익명 중첩 클래스
}
}
중첩 클래스의 장점
- 코드 그룹화:
- 특정 클래스가 다른 클래스와 강하게 연관될 때, 해당 클래스를 논리적으로 그룹화 가능.
- 캡슐화 강화:
- 외부 클래스와 관련된 클래스에 접근 범위를 제한하여 구현 세부 사항을 숨길 수 있음.
- 가독성 향상:
- 중첩 클래스를 사용하면 외부 클래스와 강한 관계를 명확히 표현 가능.
- 외부 클래스 멤버에 접근 용이:
- 비정적 중첩 클래스는 외부 클래스의 멤버에 쉽게 접근할 수 있음.
중첩 클래스의 단점
- 복잡성 증가:
- 중첩 클래스 사용이 많아지면 코드가 복잡해질 수 있음.
- 메모리 누수 위험:
- 비정적 중첩 클래스는 외부 클래스의 인스턴스를 암시적으로 참조하므로 메모리 누수가 발생할 가능성이 있음.
정리
- 정적 중첩 클래스: 외부 클래스와 독립적으로 동작.
- 비정적 중첩 클래스: 외부 클래스의 인스턴스와 밀접하게 연결.
- 지역 중첩 클래스: 특정 메서드 내에서만 사용.
- 익명 중첩 클래스: 1회성 구현에 적합.
중첩 클래스는 적절히 사용하면 코드의 논리적 그룹화를 돕고, 재사용성과 가독성을 높일 수 있는 강력한 도구입니다. 😊
LIST
'휴먼 IT 교육 수업 메모' 카테고리의 다른 글
[휴먼IT] 휴먼IT 수업 8일차 메모 (250113) (0) | 2025.01.13 |
---|---|
[휴먼IT] 수업 7일차 메모 (컬렉션) 250110 (0) | 2025.01.10 |
[휴먼IT] 휴먼IT JAVA 5일차 수업 메모 (상속) -250108 (0) | 2025.01.08 |
[휴먼IT] 휴먼IT 자바 수업 4일차 메모 (예외처리,클래스와 객체) - 250107 (1) | 2025.01.07 |
[휴먼IT] 자바 수업 3일차 메모 (반복문,배열) (0) | 2025.01.06 |