JAVA2 - Day1 - Review, abstract, interface

<Review>

package com.korea;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

System.out.println("Hello, World!");
//ctrl+F11
//compile
//JAVAC가 없으면 안된다!
//C언어 : 컴퓨터가 읽을 수 있는 언어로 변환.
//JAVA : JVM(가상머신)가 이해할 수 있는 바이트코드로 변환.

//컴파일을 하면
/* Main 클래스 로딩
* Main 함수 실행 (Static >> 로딩과 동시에 메모리에 만들어짐)
* cf. 만약 instance면 객체를 만들어야 실행된다.
*
* System 클래스 안에도 여러 멤버가 있다
* ex. java.lang >> println, printf (모두 static)
*
*/

//#2
Shape s = new Shape(10,10);
//이제 s라는 지역변수에 Shape의 주소가 담기면서 객체가 생성됨.
//컴파일하면 이제 메모리에 생성!
s.draw(); //Shape

//#3, //#4
Rect r = new Rect(20, 20);
r.draw(); //Shape >> Rect

}

}
---------------------------------------------------------------------------------------
package com.korea;

public class Shape 
{
//클래스 안에는 속성(변수)와 기능(메서드)를 넣을 수 있다~!
int x , y;
void draw() 
{
System.out.println("Shape");
}
//모두 instance 멤버.
//해당 클래스로 객체를 생성해야지만 만들어진다.
//이 상태에서 컴파일해도 메모리에 이것들이 생기지 않는다.
Shape(int x, int y)
{
//생성자
//하나이상 존재해야한다. 
//만약 없으면, 컴파일러가 기본생성자를 생성한다.
//갹체 초기화 하자
super();
//Object클래스 생성자 호출
//
this.x=x; 
this.y=y;
}
}

---------------------------------------------------------------------------------------
package com.korea;

public class Rect extends Shape 
{
Rect(int x, int y)
{
super(x, y);
//super생성자
//this()와 마찬가지로 super()도 생성자!
//this()는 같은 클래스 내의 다른 생성자를 호출하기 위해서 사용되고,
//super()는 수퍼 클래스의 생성자를 호출하는 데 사용한다.
int width, height;
}
//#4
//상속받은게 마음에 안들면 오버라이딩(재정의)
@Override
void draw() 
{
System.out.println("Rect");
}

//실행을 하면 가장먼저 object를 메모리에 생성.
//그다음 변수, 함수를 만든다.
}
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
<abstract>
 package com.absClass;

//#1
//효율적인 메모리 관리
//abstract 제어자
//클래스, 메서드 앞에도 붙일 수 있다.
//abstract 클래스 : 추상 클래스
//abstract 메서도 : 추상 메서드

//추상 클래스
// - 하나 이상의 추상메서드를 포함하고있는 클래스.
// - 클래스가 설계도라면, 추상클래스는 미완성 설계도!
// >>직접 객체를 생성할 수는 없다.
// >>추상클래스에서 정의된 추상적 기능은 자손클래스에서 상세 구현하게 된다.



public abstract class Shape //추상클래스가 됨.
//cf. 접근제어자는 무조건 하나, 나머지 제한은 갯수 제한 없다.

//추상클래스는 일반클래스가 가질수 있는 속성과 기능들을 모두 가질수 있다.
//추상메서드는 추상 클래스 안에만 들어갈 수 있다.
{
//속성과 기능
int x,y;

//추상 메서드
// - 선언부(제어자, 반환형, 이름, 매개변수)만 잇고, 구현부가 없는 메서드

//원래는..
/*
public void draw()
{

}
*/

public abstract void draw();
// - 자손클래스에서 재정의(오버라이딩)하여 사용한다.
// >>자손마다 다르게 구현될 것으로 예상되는 경우,
// >>필요한 프레임워크(틀)을 제공한다.

public Shape(int x, int y)
{
this.x = x; this.y =y;
//this 레퍼런스
//인스턴스 메소드 내부에 선언하지 않고 지역변수처럼 사용된다.
//자기 자신만을 가리키는 레퍼런스로서 메소드 내부의 모든 인스턴스 필드와 메소드 앞에 암시적으로 사용된다.
//필요에 따라 명시적으로 사용할 수 있다.

//this를 언제 사용해야 할까?
/*
* 매개변수의 이름이 필드와 같은 경우 this로 필드와 매개변수를 구분.
* this는 해당 인스턴스의 멤버임을 알리는 표시방법으로 사용된다.
* 그러나 지역변수와 필드의 이름이 같은 특수한 상황이 아니라면  this를 붙이지 않아도 무방하다.
*/

}
}
---------------------------------------------------------------------------------------
package com.absClass;

public class Main
{
//패키지가 다르면 클래스이름이 같아도 상관 없다!

public static void main(String[] args)
{

Shape shape; //자료형으로는 쓸 수 있다.
//Shape shape = new Shape(); 객체 생성은 불가능

//#1 --Rect
System.out.println();
System.out.println("#1");
/*
Rect rect = new Rect();
Circle circle = new Circle();
Rect.draw();
circle.draw();
*/

//#2
System.out.println();
System.out.println("#2");
//이렇게 하도록 재정의 해보자.
Rect rect = new Rect(10, 20,50,50); //Rect (x,y,width,height)
Circle circle = new Circle(15,15,5); //Circle (x, y, radius)

rect.draw();
circle.draw();

//#3
System.out.println();
System.out.println("#3");
//배열에 객체 넣기. (권장하지 않음.)
//다형성(객체의 형변환)
// - 서로 상속관계에 있는 타입간의만 형변환이 가능하다.
// >>조상타입변수 = 자손타입갹채 (가능)  = 업 캐스팅. //상속관계만 만족하면 다 된다.
// >>자식타입변수 = 조상타입객체 (불가능) = 다운 캐스팅. // 들어있는 실제객체와 캐스팅이 같아야 가능.
Shape shape2;
//shape 클래스의 자손 클래스 객체를 담을 수 있다.

Shape [] list = new Shape [2];
list [0] = rect;
list [1] = circle;

//자식클래스의 멤버변수에는 접근이 불가능하다.
System.out.println(list[0].x);
System.out.println(list[0].y);
// System.out.println(list[0].width); 에러난다.
//width라는 상제에는 접근이 안되기 때문.
//list는 shape객체라고 인식하여 width, height가 메모리가 존재함에도 불구하고 접근 x

System.out.println(list[1].x);
System.out.println(list[1].y);
//System.out.println(list[1].radius);

//조상클래스 멤버변수에는 얼마든지 접근할 수 있다.
list[0].draw(); // Rect 출력됨.
list[1].draw(); // Circle 출력됨.

//#4
System.out.println();
System.out.println("#4");
//다운 캐스팅
//Rect r =list[0];
//자식 객체에 조상타입을 넣는것이기 때문에 불가능.
//배열의 형식이 조상이기 때문에 안된다!
//억지로 집어넣어줄 수는 있다.
//캐스팅!

Rect r1 = (Rect)list[0];

//주의할 점!
//이렇게 해도 가능하다.
//Rect r2 = (Rect)list[1];
//실행시키면 에러가 뜬다.
//Circle객체가 들어가 있기 때문.

//#5
System.out.println();
System.out.println("#5");
//에러의 두가지 종류
//컴파일 과정에서 뜨는 에러. >> 빨간줄
//일단 컴파일 되고, 실핼할 때 나는 에러.
//위의 Rect r2 = (Rect)list[1]; 에러는 두번째 에러.

Circle c1 = (Circle)list[1];


//#6
System.out.println();
System.out.println("#6");
//배열에 들어있는 실제 객체가 어떤 타입 객체인지 어떻게 알까?
//뒤져서 하는거 말고..
//확인하는 방법!!
//instanceof 연산자
// - 객체의 실제 타입을 파악할 수 있다.
// - 객체가 클래스나 인터페이스(아직 공부 안 한 과정~)로부터 생성된 객체인지를 판별하여
// - boolean값을 (true / false) 반환한다.
// - 객체 변수 instanceof /*궁금한*/클래스명 or 인터페이스명

if(list[0] instanceof Rect)
{
System.out.println("형변환 가능");
}
else
{
System.out.println("형변환 불가능");
}

}

}
---------------------------------------------------------------------------------------
package com.absClass;

public class Rect extends Shape
{

int width, height;
//#1
//에러 발생!
//Shape이란 클래스를 상속 받았는데,
//그럼 Shape이 가진 멤버를 다 갖고 왔겠지?
//object, draw, 변수 등등등

//Rect는 추상클래스가 아닌 일반 클래스이기때문에
//추상 메서드를 가질 수 가 없다.
//그래서 오류가 발생

//해결하는 방법 #1
//Rect를 추상클래스로 만들자.
//근데 이렇게하면 Rect로 객체를 만들 수 없다.

//해결하는 방법 #2
//미완성인 클래스를 완성시키자.
//재정의(오버라이딩)
@Override
public void draw()
{
System.out.println("Rect");
}

public Rect (int x, int y, int width, int height)
{

//super는 항상 첫줄에!
//순서 바뀌면 안된다.

//조상으로부터 받은 변수
super(x, y);

//내가 받은 변수
this.width = width;
this.height = height;

}

}
---------------------------------------------------------------------------------------
package com.absClass;

public class Circle extends Shape 
{
int radius;
@Override
public void draw()
{
System.out.println("Circle");
}
public Circle (int x, int y , int radius)
{
//super는 항상 첫줄에!
//순서 바뀌면 안된다.
//조상으로부터 받은 변수
super(x, y);
//내가 받은 변수
this.radius=radius;
}
}
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
<interface>
package com.poly;
//#1
//인터페이스
// - 추상클래스보다 더 완벽한 추상화 제공.
// (실제로 구현된 것이 전혀 없는 설계도)
//속성과 기능을 갖지 못하고 상수와 추상 메서드만 가질 수 있다.
//이 때 상수는 (public static final) 제어자를 갖고
//추상메서드는 (public abstract)를 갖게 된다.

//사용하는 이유
// - 클래스 작성에 도움을 줄 목적으로 사용된다.

//인터페이스를 사용하는 목적
// - 미리 정해진 규칙에 맞게 구현하도록 표준을 제시해준다
// - 아무 상관없는 클래스를 묶어줄때
// - 기타 등등 

//인터페이스도 클래스와 마찬가지로 하나의 페이지에 하나만 만드는 것을 권장.
//public 때문.
//지금은 보기 좋게 하나에 다 쓴다!

interface CA
{
//상수와 추상메서드만 가능!
String phone = "820-0000";
void call();
}

//#2
//인터페이스 상속
//인터페이스 상속에는 두가지가 있다.
//기본적으로 조상걸 다 받는 것.
// - 인터페이스에서 인터페이스 상속
// interface I1 extends I2, I3, ...{}
// >>인터페이스는 다중 상속을 허용한다!

//인터페이스 구현
// - 인터페이스가 의미를 가지러면 클래스에서 인터페이스를 상속받아야한다.
// - 그 과정을 인터페이스 구현이라고 한다. (implements)
// class C1 implements I1 {}
// >>인터페이스에서 정의된 추상메서드를 오버라이딩시켜줘야 한다.
// - 다음과 같이 활용도 가능하다.
// >>class C1 extends C2 implements I1{}

public interface korea /*#2*/extends CA
{
String addr = "서울특별시 테헤란로";
//인터페이스에서는 원래 이렇게 안되는데
//자바에서 자동으로 public static final를 붙여줘서 가능해진다.
//어차피 키워드는 저것밖에 못쓰니까 자동으로 붙여주는것.
//즉, 사실 상수로 기능하게 되는것.
//상수이기 때문에 초기화를 안하면 에러가 난다.
//void fn();
//이 또한 마찬가지로 자동으로 public abstract를 붙여준다.
}
---------------------------------------------------------------------------------------
package com.poly;

public class Main
{
//#2
//motivator
//Monster클래스의 자손클래스를 매개변수를 넘겨받아
//attack메서드를 호출하자.
/*
public static void attackMonster(Cat c) {
c.attack();
}
public static void attackMonster(Rabbit r) {
r.attack();
}
하는 행위가 똑같으니까 다형성이라는 특징을 이용하여 간결하게 하자.
*/
public static void attackMonster(Monster m) {
m.attack();
}
//#3
//Monster클래스의 자손 클래스를 매개변수로 넘겨받아 attack매서드 호출
public static Monster attack1Monster(Monster m) {
m.attack();
return new Rabbit();
//토끼 객체(자식)을 조상객체에 할당.
}
//#5
//Korea인터페이스의 자손 클래스를 매개변수로 넘겨받아 attack메서드 호출
public static void attackKorea(korea k) {
//k.attack();
//안된다. Korea에 attack메서드가 없기 때문이다.
//다운캐스팅을 하자.
if(k instanceof Monster) {
Monster m = (Monster)k;
m.attack();
//(Monster)k.attack(); 하면 에러난다.
// .attack()이 우선순위가 있기 때문.
//((Monster)k).attack(); 이렇게 바꾸자.
}
else {
Unit u = (Unit)k;
u.attack();
}
}

public static void main(String[] args)  {
//#1
//부모타입에 자손객체 넣기.
Monster[] monList = new Monster[2];
monList[0] = new Cat();
monList[1] = new Rabbit();
Unit[] unitList = new Unit[2];
unitList[0] = new Blue();
unitList[0] = new YoTu();
//#2'
System.out.println("#2");
attackMonster(new Cat());
attackMonster(new Rabbit());

//#3'
System.out.println();
System.out.println("#3");
Monster r1= attack1Monster(new Rabbit());
Rabbit r2 = (Rabbit)attack1Monster(new Rabbit());

//#4
System.out.println();
System.out.println("#4");
//인터페이스
korea k; 
//Korea 인터페이스를 구현하고 있는 클래스 객체
//Korea k = new Korea(); (불가능)
korea[] koreaList = new korea [4];
koreaList[0] = new Cat();
koreaList[1] = new Rabbit();
koreaList[2] = new Blue();
koreaList[3] = new YoTu();
//조상이니까 모두 담을수 있다.
//다만, 조상멤버에만 접근 가능.
//연관없던 몬스터와 유닛을 같이 묶을 수 있게 되었다.
//#5'
attackKorea(new YoTu());
attackKorea(new Blue());
}


}
---------------------------------------------------------------------------------------
package com.poly;

public abstract class Monster /*인터페이스*/ implements korea
{
int hp,mp;
/*
void attack()
//생각해보니 몬스터 마다 다른 공격방식을 갖고 있을것 같다. 추상으로 만들자.
{

}
*/

abstract void attack();
//클래스도 abstract로 만드는것 잊지말기!

void move() {
System.out.println("이동합니다.");
}
}


class Cat extends Monster
{
//추상메서드 상속 받았으니 오버라이딩 하자.
@Override
void attack() {
System.out.println("할퀴기 공격");
}


//인터페이스 오버라이딩
public void call()
{
System.out.println("전화합니다!");
}

}

class Rabbit extends Monster
{
@Override
void attack() {
System.out.println("물어뜯기 공격");

}

//인터페이스 오버라이딩
public void call()
{
System.out.println("전화합니다!");
}
}
---------------------------------------------------------------------------------------
package com.poly;

public abstract class Unit implements korea
{
int hp, mp;
abstract void attack();
void move() {
System.out.println("이동합니다.");
}
void defense() {
System.out.println("방어합니다.");
}
@Override
public void call() {
System.out.println("전화합니다");
}
}


class Blue extends Unit
{
void attack() {
System.out.println("용의 숨결!");
}
//인터페이스 오버라이딩
public void call()
{
System.out.println("전화합니다!");
}
}

class YoTu extends Unit
{
void attack() {
System.out.println("브레인 데미지!");
}
//인터페이스 오버라이딩
public void call()
{
System.out.println("전화합니다!");
}
}

댓글

이 블로그의 인기 게시물

11 - Scanf

JAVA - Day3 - Scanner, if, if else

JAVA - Day5 - Array,Random