제네릭은 클래스 안에 들어갈 자료형을 선언 및 초기화시 정할 수 있는 것을 말한다.

package coffeeshop.test;

class Data1 {
	
	// 오브젝트 자료형은 받기는 쉬우나 받은뒤 사용하려면 캐스팅 해야하기 때문에 불편
	Object data;
}


// 제네릭
class Data <T> {
	T value;
}

// 콤마를 통해서 두개를 넣을 수 있다
class Str<K, V>{
	K k;
	V v;
}


public class GenericEx01 {
	public static void main(String[] args) {
		Data1 data1 = new Data1();
		data1.data = "오브젝트자료형";
		System.out.println((String)data1.data);
		
		
		
		Data<String> data = new Data<>();
		data.value = "제네릭문자열";
		System.out.println(data.value);
		
		// 제네릭에는 기본자료형이 들어갈 수 없다 (Wrapper 클래스로 감싸야한다)
		// Wrapper 클래스 = 기본자료형에 첫글자에 대문자(클래스자료형처럼) (기본자료형의 수만큼 있음)
		// int -> Integer / char -> Character
		Data<Integer> data2 = new Data<>(); 
		
		data2.value = 10;
		System.out.println(data2.value);
		
		
		Str<String, String> s = new Str<>();
		s.k = "비밀번호";
		s.v = "bitc5500";
		
		System.out.println(s.k);
		System.out.println(s.v);
	}
}

1.손님이 커피숍에 들어간다

오브젝트 손님
오브젝트 커피숍

------------------

2.손님이 바리스타에게 가서 주문

오브젝트 바리스타

---------------------

3.손님이 메뉴판을 본다

오브젝트 메뉴판
오브젝트 메뉴목록
오브젝트 메뉴

---------------------

4.손님이 바리스타에게 아메리카노를 주문한다

---------------------

5.바리스타가 아메리카노를 만든다

---------------------

6.바리스타가 아메리카노를 손님에게 준다

-----------------------

객체지향 프로그래밍에서는 현실에서 생명이 없는 것들도 살아있는 것처럼 취급한다.

오브젝트들은 각자의 역할이 있고 협력을 한다

오브젝트 => 역할(부모클래스) => 책임(메서드)

오브젝트 => 협력 => 메시지(함수의 호출)

역할, 책임, 협력, 메시지 -- 네개가 합쳐져서 객체지향을 이룬다 

역할은 대체될 수 없고 (부모클래스, 추상클래스, 인터페이스) 그 아래 오브젝트는 대체 될 수 있다.
(Protoss=역할 Object=질럿,드라군)

책임 없이 데이터만 있는 애들 - 클래스 자료형 : Beans, Model, 데이터베이스의 테이블

----------------------

배열
- 빠르다, 생성 후 배열길이를 줄이거나 늘릴 수 없다

링크드 리스트
- 느리다, 배열길이를 줄이거나 늘릴 수 있다

어레이리스트
- 배열길이를 줄이거나 늘릴 수 있다
- 순차적으로 정렬되서 랜덤엑세스가 가능하다(검색효율이 뛰어나다)
- 수정 삭제시 링크드 리스트 보다 느리다

----------------------------

 

 

 

기본버거 콜라 감자튀김을 만든다

package composite;

import lombok.Data;

@Data // getter, setter 생성
public class Burger {
	private int price;
	private String desc;

	public Burger() {
		this(1500, "기본버거");
	}

	public Burger(int price, String desc) {
		this.price = price;
		this.desc = desc;
		System.out.println(desc + "가 만들어졌습니다.");
	}
}
package composite;

import lombok.Data;

@Data
public class Coke {
	private int price;
	private String desc;
	
	public Coke() {
		this(1500, "코카콜라");
	}
	
	public Coke(int price, String desc) {
		this.price = price;
		this.desc = desc;
		System.out.println(desc + "가 만들어졌습니다.");
	}
}
package composite;

import lombok.Data;

@Data
public class FrenchFried {
	private int price;
	private String desc;
	
	public FrenchFried() {
		this(2000, "감자칩");
	}
	
	public FrenchFried(int price, String desc) {
		this.price = price;
		this.desc = desc;
		System.out.println(desc + "이 만들어졌습니다.");
	}
}

 

버거를 상속 받아 빅버거와 쉬림프버거를 만든다

package composite;

public class BigBurger extends Burger {
	public BigBurger() {
		super(4000, "빅버거");
	}
	
	public BigBurger(int price, String desc) {
		super(price, desc);
	}
}
package composite;

public class ShrimpBurger extends Burger {

	public ShrimpBurger() {
		super(3500, "쉬림프버거");
	}

	public ShrimpBurger(int price, String desc) {
		super(price, desc);
	}
}

 

 

 

콤포지션

- 상속이 아닌 만들어 놓은 클래스를 가져오는 것

 

빅버거, 쉬림프버거, 감자튀김, 콜라 를 이용해서 세트를 만들기

package composite;

import lombok.Data;

// 자바는 다중 상속이 안됨 (부모가 여럿이 될 수 없음)

@Data
public class BigBurgerSet {
	// 콤포지션(중요) - 상속이 아닌 만들어 놓은 클래스를 가져오는 것
	private BigBurger bigBurger;
	private Coke coke;
	private FrenchFried frenchFried;
	
	public BigBurgerSet() {
		this(new BigBurger(), new Coke(), new FrenchFried());
	}

	public BigBurgerSet(BigBurger bigBurger, Coke coke, FrenchFried frenchFried) {
		this.bigBurger = bigBurger;
		this.coke = coke;
		this.frenchFried = frenchFried;
	}

}
package composite;

import lombok.Data;

@Data
public class ShrimpBurgerSet {

	// 콤포지션(중요) - 상속이 아닌 만들어 놓은 클래스를 가져오는 것
	private ShrimpBurger shrimpBurger;
	private Coke coke;
	private FrenchFried frenchFried;

	public ShrimpBurgerSet() {
			this(new ShrimpBurger(), new Coke(), new FrenchFried());
		}

	public ShrimpBurgerSet(ShrimpBurger shrimpBurger, Coke coke, FrenchFried frenchFried) {
			this.shrimpBurger = shrimpBurger;
			this.coke = coke;
			this.frenchFried = frenchFried;

		}

}

 

실행 파일을 만들어서 실행해보기

package composite;

public class LotteriaApp {
	public static void main(String[] args) {
		// 빅버거 세트
		BigBurgerSet set1 = new BigBurgerSet();
		
		System.out.println();
		
		// 기본버거
		Burger burger1 = new Burger();
		
		System.out.println();
		
		// 콜라
		Coke coke1 = new Coke();
		
		System.out.println();
		
		
		// BigBurgerSet
		BigBurgerSet set2 = new BigBurgerSet(
				new BigBurger(3000, "빅버거할인"),
				new Coke(),
				new FrenchFried()	
				);
		
		System.out.println();
		
		BigBurgerSet set3 = new BigBurgerSet(
				new BigBurger(2000, "빅버거할인"),
				new Coke(),
				new FrenchFried()
				);
		
		System.out.println();
		
		
		// 새우버거 세트 추가요
		ShrimpBurgerSet set4 = new ShrimpBurgerSet();
		
		System.out.println();
	}
}

 

생성자 오버로딩

package composite;

import lombok.Data;

@Data
public class ShrimpBurgerSet {

	// 콤포지션(중요) - 상속이 아닌 만들어 놓은 클래스를 가져오는 것
	private ShrimpBurger shrimpBurger;
	private Coke coke;
	private FrenchFried frenchFried;
	
	public ShrimpBurgerSet() {
		this(new ShrimpBurger(), new Coke(), new FrenchFried());
	}
	
	public ShrimpBurgerSet(ShrimpBurger shrimpBurger) {
		this(shrimpBurger, new Coke(), new FrenchFried());
	}
	
	public ShrimpBurgerSet(Coke coke) {
		this(new ShrimpBurger(), coke, new FrenchFried());
	}
	
	public ShrimpBurgerSet(FrenchFried frenchFried) {
		this(new ShrimpBurger(), new Coke(), frenchFried);
	}
	
	public ShrimpBurgerSet(ShrimpBurger shrimpBurger, Coke coke) {
		this(shrimpBurger, coke, new FrenchFried());
	}
	
	public ShrimpBurgerSet(ShrimpBurger shrimpBurger, FrenchFried frenchFried) {
		this(shrimpBurger, new Coke(), frenchFried);
	}
	
	public ShrimpBurgerSet(Coke coke, FrenchFried frenchFried) {
		this(new ShrimpBurger(), coke, frenchFried);
	}
	
	
	// 생성자가 제일 많은 것이 기준
	public ShrimpBurgerSet(ShrimpBurger shrimpBurger, Coke coke, FrenchFried frenchFried) {
		this.shrimpBurger = shrimpBurger;
		this.coke = coke;
		this.frenchFried = frenchFried;
	}
	
	public static void main(String[] args) {
		ShrimpBurgerSet s1 = new ShrimpBurgerSet(new Coke(), new FrenchFried());
	}
}

 

셀프조인 SELF JOIN

자신의 테이블에서 자신의 테이블을 조인하는 것

 

SELECT E1.EMPNO, E1.ENAME, E1.JOB, E1.MGR, E2.ENAME
FROM EMP E1, EMP E2
WHERE E1.MGR = E2.EMPNO;

.

package animal;

// 인터페이스의 변수와 함수
// 1. 변수 : public static final 생략
// 2. 함수 : public abstract 생략
// 3. 통로의 역할 - 동적 바인딩
// 4. 무조건 추상메서드만 존재가능 -> 강제성부여
// 5. new 할 수 없다

// 고정된 범위의 값을 주는 것을 [도메인]을 준다고 한다
interface 부서 {
	int 총무과 = 10; // 공통코드
	int 생산팀 = 20; // 공통코드
	int 인사과 = 30; // 공통코드
	int 행정과 = 40; // 공통코드
}

interface Cal {
	int num = 10; // 인터페이스의 변수는 무조건 public static final 이다.
}

public class InterfaceEx01 {
	public static void main(String[] args) {
		System.out.println(Cal.num);
	}
}

 

인터페이스

package stars1;

// 인터페이스는 추상 클래스와 유사
// 다른점 : 추상 메서드만 존재가능
// 동적 바인딩의 통로로만 사용
// 메서드에 public abstract를 생략가능
// 제작자와 이용자의 약속 - 키보드에서 a를 누르면 작동원리를 몰라도 컴퓨터에 a가 입력된다
// 프로토콜 : 동등한 관계의 상호 협의하에 이루어진 약속
// 인터페이스 : 제작자가 사용법만 알려주고 이용자가 사용하는 식의 약속

public interface Behavior {
	public abstract void move();

	public void repair();

	void attack(Behavior unit);
	
	public String getName();
	
	public int getHp();
	
	public void setHp(int hp);
}


 

추상클래스

package stars1.protoss;

import stars1.Behavior;

public abstract class Protoss implements Behavior {

	// 움직임과 쉴드 치료는 프로토스 유닛 공통이기 때문에 추상 클래스에 바로 만들어준다
    // 이렇게 만든 공통 메서드들은 구체클래스들에 구현하지 않아도 되서 어댑터 역할도 한다

	@Override
	public void move() {
		System.out.println("이동");
		
	}
	
	@Override
	public void repair() {
		System.out.println("쉴드 치료");
		
	}
	
	public static void upgrade() {
		Zealot.attack++;
		Dragoon.attack++;
		System.out.println("프로토스 업그레이드 완료");
	}
}

 

일반 클래스

package stars1.protoss;

import stars1.Behavior;

public class Zealot extends Protoss {
	private String name;
	private int hp;
	private int sh; // 보호막
	public static int attack = 10;

	public Zealot(String name) {
		this.name = name;
		this.hp = 100;
		this.sh = 100;
	}

	@Override
	public void attack(Behavior unit) {
		unit.setHp(unit.getHp() - attack);
		System.out.println(unit.getHp());
	}
	
	@Override
	public int getHp() {
		return hp;
	}
	
	@Override
	public void setHp(int hp) {
		this.hp = hp;
	}
	
	@Override
	public String getName() {
		return name;
	}
	
}

 

메인

package stars1;

import stars1.protoss.Dragoon;
import stars1.protoss.Protoss;
import stars1.protoss.Zealot;

public class StartGame {

	public static void move(Behavior b) {
		b.move();
	}
	
	public static void repair(Behavior b) {
		b.repair();
	}
	
	public static void attack(Behavior b1, Behavior b2) {
		System.out.println(b1.getName() + "이 " + b2.getName() + "을 공격했습니다.");
		System.out.println(b2.getName() + "의 현재 체력");
		b1.attack(b2);
	}
	
	public static void main(String[] args) {
		Protoss.upgrade();
		Zealot z1 = new Zealot("질럿1");
		Zealot z2 = new Zealot("질럿2");
		Dragoon d1 = new Dragoon("드라군1");
		attack(z1, d1);
		repair(z1);
		
	}
}

 

 

package ch05;

// 추상 클래스는 new 할 수 없다. 오브젝트가 아니기 때문.
// 추상 클래스는 추상 메서드를 가질 수 있다.
abstract class Food {
	abstract void eat();
}

class 라면 extends Food {

	String name = "라면";

	@Override
	void eat() {
		System.out.println(name + "을 먹었습니다.");
	}

}

class 불고기 extends Food {

	String name = "불고기";

	@Override
	void eat() {
		System.out.println(name + "를 먹었습니다.");
	}

}

class 갈비 extends Food {

	String name = "갈비";

	@Override
	void eat() {
		System.out.println(name + "를 먹었습니다.");
	}

}

public class FoodEx01 {

	static void start(Food f) {
		f.eat();
	}

	public static void main(String[] args) {
		start(new 라면());
	}
}

 

공통 사항은 추상 클래스에서 메서드를 구현해도된다.

package ch05;

abstract class Food {

	void eat() {
		System.out.println("음식을 먹습니다."); // 공통적인것은 사용
	}

	abstract void cook(); // 공통적인데 오브젝트마다 조금씩 다르다면 추상메서드 사용
}

class 라면 extends Food {

	@Override
	void cook() {
		System.out.println("냄비에 끓인다.");

	}

}

class 삼겹살 extends Food {

	@Override
	void cook() {
		System.out.println("불판에 굽는다.");
	}

}

public class FoodEx02 {
	
	static void start(Food f) {
		f.cook();
		f.eat();
	}
	
	
	public static void main(String[] args) {
		start(new 라면());
	}
}

 

추상클래스를 이용해 순서를 정할 수 있다.

package ch05;


// 추상 클래스는 일반 메서드를 가질 수 있다.
// 추상 클래스는 내가 구현할 수 없는 메서드를 오브젝트에게 미룰 수 있다.
// 추상 클래스는 abstract를 붙인다.
// 추상 클래스를 통해서 순서를 정할 수 있다.
abstract class Food {
	
	abstract void standby();
	
	// protected는 자식만 사용가능
	
	protected void eat() {
		System.out.println("음식을 먹습니다."); // 공통적인것은 사용
	}

	abstract void cook(); // 공통적인데 오브젝트마다 조금씩 다르다면 추상메서드 사용
	
	void auto() {  // 이렇게 제작하면 순서 실수를 하지 않는다 (요리 -> 섭취)
		standby();
		cook();
		eat();
	}
}

class 라면 extends Food {
	
	

	@Override
	void cook() {
		System.out.println("냄비에 끓입니다.");

	}

	@Override
	void standby() {
		System.out.println("라면과 냄비를 준비합니다.");
		
	}

}

class 삼겹살 extends Food {

	@Override
	void cook() {
		System.out.println("불판에 굽습니다.");
	}
	
	@Override
	void standby() {
		System.out.println("고기와 불판을 준비합니다.");
		
	}

}

public class FoodEx02 {
	
	static void start(Food f) {
		f.auto();
	}
	
	
	public static void main(String[] args) {
		start(new 라면());
	}
}

 

추상 클래스를 어댑터 용도로 사용

package ch05;

// 어댑터

abstract class 칼 {
	abstract void kill();

	abstract void cook();

	abstract void repair();
}


// 상속 받는 추상 클래스는 부모 클래스의 모든 클래스를 오버라이딩 할 필요가 없다.
// 요리사 어댑터 - 필요없는 기능만 입력한다. (cook메서드만 자식클래스에 구현을 미룬다.)
abstract class 요리사 extends 칼 {
	
	@Override
	void kill() {}
	
	@Override
	void repair() {}
}

// 요리사 클래스가 구현하지 않은 기능만 구현하면 된다.
class 백종원 extends 요리사{
	
	@Override
	void cook() {
		// TODO Auto-generated method stub
		
	}
}

public class FoodEx03 {
	public static void main(String[] args) {

	}
}

 

 

주의 : 이클립스 또는 STS를 한글디렉토리 또는 띄어쓰기가 있는 디렉토리에 설치하신 분은 프로그램이 실행 안될 가능성이 있습니다. 띄어쓰기 없는 영문명 디렉토리에 IDE를 설치해주세요

 

 

 

 

 

 

 

 

 

 

 

 

 

롬복을 사용하면 게터와 세터를 자동으로 만들어준다

package stars1.protoss;

import lombok.Data;

@Data
public class Zealot{
	private String name;
	private int hp;
	private static int attack;
	
	public static void main(String[] args) {
		Zealot z1 = new Zealot();
		z1.getName();
		z1.setHp(10);
		
	}
}

 

게터만 만들려면

package stars1.protoss;

import lombok.Getter;

@Getter
public class Zealot{
	private String name;
	private int hp;
	private static int attack;
	
	public static void main(String[] args) {
		Zealot z1 = new Zealot();
		z1.getName();
		z1.setHp(10);
		
	}
}

 

롬복 디폴트생성자, 모든 변수 생성자, 게터 세터

package stars1.protoss;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


// 어노테이션 - 컴파일러가 읽고 해당 내용을 코드를 띄우기전에 먼저 동작
@AllArgsConstructor // 모든 힙 변수를 받는 생성자 자동생성
@NoArgsConstructor // 디폴트 생성자 자동생성
@Data // 게터와 세터 자동생성 @Getter @Setter 를 이용할 수도 있다.
public class Zealot{
	private String name;
	private int hp;
	private static int attack;
}

 

 

+ Recent posts