상속의 효과 중 재산을 물려받는 것은 부가적인 것, 주 목적은 추상화를 통해 타입을 일치시키기 위한 것임.
--> 체계적 개발 및 OOP 구현(다형성 확보)에 도움, 편의성↑
ex)xxx, xxx 차렷 -> X , 일동 차렷(O)
package ex05.composit;
//생성자, 게터는 기본 생성 -> 세터는 필요할 때만
public class BurgerSet {
private Burger burger;
private Coke coke;
private Potato potato;
public BurgerSet() {
this(new Burger(), new Coke(), new Potato());
// 매개변수 자리에 new () -> 힙 주소 전달됨.
// new Burger(); 라고만 적으면 가비지컬렉션 대상이지만, 위 방법 처럼하면 실제적으로 값이 전달되므로 가비지컬렉션 대상X
}
private BurgerSet(Burger burger, Coke coke, Potato potato) {
this.burger = burger;
this.coke = coke;
this.potato = potato;
}
public Burger getBurger() {
return burger;
}
public Coke getCoke() {
return coke;
}
public Potato getPotato() {
return potato;
}
}
package practice;
public class AppEx02 {
public static void main(String[] args) {
BurgerSet bs2 = new BurgerSet();
int setPrice = bs2.getPotato().getPrice() + bs2.getCoke().getPrice() + bs2.getPotato().getPrice();
String setDesc = bs2.getPotato().getDesc() + ", " + bs2.getCoke().getDesc() + ", " + bs2.getBurger().getDesc();
System.out.println("버거세트의 가격은" + setPrice + "입니다.");
System.out.println("버거세트는의 구성은 " + setDesc + "입니다.");
}
}
==> D는 DIP(의존성 역전 원칙), 추상적인 것에 의존하도록 하는 것
==> O는 OCP(개방폐쇄원칙), 새로운 파일 만드는 것은 ok, 기존 코드의 변경은 X
DIP를 지키면 자연스럽게 지켜짐
주체가 달라지면 코드를 다시 써야하는 상황이 발생하지 않도록
주체(구체적인 것)에 의존하지 않고, 추상적인 것에 의존하도록 코드를 만드는 것
ex)
왕.심문() , 왕비 심문() --> X
재판관.심문() --> O
String str ="";
Object obj = str
String 타입인 str을 최상위 클래스 Object타입의 obj 변수에 담을 수 있다.
이유는 상속과 관련이 있다. Object는 최상위 클래스이고, 자식 클래스인 str은
Object클래스를 상속했으므로, 부모 클래스 타입으로 선언될 수 있기 때문이다.
따라서 str은 묵시적 형변환이 되어 Object 타입으로 obj에 저장된다.
int b= 5;
Object obj = b;
와 같이 클래스 타입이 아닌 변수 b의 경우도 Object 타입의 변수에 담을 수 있다.
-->
자바에서 int 타입의 경우 Integer 타입의 객체로 자동 변환하여 처리하기 때문이다.
package ex06;
/**
* 1. 추상클래스는 new 할 수 없다.
* 2. 추상클래스는 일반메서드와 추상메서드를 가질 수 있다.
* 3. 추상클래스는 상태변수를 가질 수 있다.
*/
abstract class 동물 {
String name;
// 일반 메서드는 공통된 것을 규정
// 추상 메서드는 하위 클래스에서 구현하는 것이 각각 달라져야 할 때 사용
public void run() {
System.out.println("달린다");
}
public abstract void speak();
}
class 사자 extends 동물 {
@Override
public void speak() {
System.out.println("어흥");
}
}
public class Abstract01 {
public static void main(String[] args) {
// new 동물();
}
}
package ex06;
//싱글톤 패턴 - new해서 1개만 유지시키고 싶을 때, 더 이상 생성X(바론)
class 미니언 {
public 미니언() {
System.out.println("미니언이 생성되었습니다.");
}
}
//싱글톤 패턴 만들기
//생성자에 Private 붙이기: 클래스 외부에서 해당 클래스의 인스턴스를 생성할 수 없게 만들고, 상속을 통한 새로운 인스턴스 생성을 방지
//private static 제어자를 활용하여 인스턴스를 생성하는 코드를 클래스 영역에 작성
//이후 getInstance 메서드를 작성하여 instance값을 가져오기.
class 바론 {
private static 바론 instance = new 바론();
private 바론() {
}
public static 바론 getInstance() {
return instance;
}
}
public class Single01 {
public static void main(String[] args) {
미니언 m1 = new 미니언();
미니언 m2 = new 미니언();
미니언 m3 = new 미니언();
System.out.println(m1.hashCode());
System.out.println(m2.hashCode());
System.out.println(m3.hashCode());
바론 b1 = 바론.getInstance();
바론 b2 = 바론.getInstance();
System.out.println(b1.hashCode());
System.out.println(b2.hashCode());
if (b1 instanceof 바론) {
System.out.println("같은 타입 입니다.");
}
if (b1 instanceof Object) {
System.out.println("바론과 오브젝트는 같은 타입입니다.");
}
}
}
package ex06;
/**
* 인터페이스는 new할 수 없다.
* 인터페이스는 static 변수를 만들 수 있다.
* 인터페이스는 추상메서드만 가진다.
* 인터페이스는 두 가지 관점에서 사용 - 노출, 강제성
*/
interface Remote {
int NUM = 10; // public static final 생략
void run(); // public abstract 생략
}
public class Inter01 {
public static void main(String[] args) {
System.out.println(Remote.NUM);
}
}
package ex06;
interface Remocon {
void on();
void off();
}
class 삼성 implements Remocon {
@Override
public void off() {
System.out.println("티비 끄다");
}
@Override
public void on() {
System.out.println("티비 켜다");
}
}
class 엘지 implements Remocon {
@Override
public void off() {
System.out.println("티비 끄다");
}
@Override
public void on() {
System.out.println("티비 켜다");
}
}
public class Inter02 {
public static void main(String[] args) {
Remocon s1 = new 삼성();
s1.on();
s1.off();
Remocon s2 = new 엘지();
s2.on();
s2.off();
}
}
package ex06;
// 구현체 : Car
interface CarAble {
void 전진();
void 후진();
void 스탑();
}
// 인터페이스 보세요!!
class Car implements CarAble {
private void a1() {
}
private void a2() {
}
private void a3() {
}
private void a4() {
}
private void a5() {
}
private void a6() {
}
private void a7() {
}
private void a8() {
}
// 앞으로 가게 하려면 a1, a3, a5, a6 를 순서대로 호출해
// 뒤로 가게 하려면 a8, a7, a6, a5 순서대로 호출해
// 멈추려면 a3, a7 호출하면 돼
@Override
public void 전진() {
a1();
a3();
a5();
a6();
System.out.println("전진함");
}
@Override
public void 후진() {
a8();
a7();
a6();
a5();
System.out.println("후진함");
}
@Override
public void 스탑() {
a3();
a7();
System.out.println("멈춤");
}
}
public class Inter03 {
public static void start(CarAble c) {
c.전진();
c.스탑();
c.후진();
}
public static void main(String[] args) {
start(new Car());
}
}
전체가 부분에 영향을 미친다 -> 구성
전체가 부분에 영향을 미치지 않는다 - > 집합