2008. 8. 6. 15:22

Part 2 & 3 메소드와 클래스

1. 메소드 오버로딩이란?
한 메소드에 대해 여러번 정의할 수 있는데 이름이 같아도 메소드의 자료형과 전달인자의 개수로 구분이 가능하다.

package training;
class YourMath {
 static double max=0;
 public static int max(int a,int b) {
  if(a>b)
   max=a;
  else
   max=b;
  return (int)max;
 }
 public static long max(long a,long b) {
  if(a>b)
   max=a;
  else
   max=b;
  return (long)max;
 }
 public static float max(float a,float b) {
  if(a>b)
   max=a;
  else
   max=b;
  return (float) max;
 }
 public static double max(double a,double b) {
  if(a>b)
   max=a;
  else
   max=b;
  return max;
 }
}
public class Ex02 {
 public static void main(String[] args) {
  System.out.println(YourMath.max(10, 20));
  System.out.println(YourMath.max(4L, 2L));
  System.out.println(YourMath.max(4.2f, 2.3f));
  System.out.println(YourMath.max(4.24, 2.35f));
 }

}

2. Varargs
메소드 내의 기능이 같더라도 전달인자의 개수에 따라 다양하게 호출하기 위해서는 메소드를 여러번 정의해야 하지만 아래처럼 Varargs를 쓰면 한방에 끝난다.

// Varargs를 이용한 출력
package training;
public class Ex04 {
 public static void prn(int ... a){
  for(int i=0;i<a.length;i++)
   System.out.print(a[i] + " ");
  System.out.println();
 }
 public static void main(String[] args) {
  prn(10);
  prn(10,20);
  prn(10,20,30);
 }
}

3. 레퍼런스와 지역변수의 변화를 확인하는 소스
package pack03;
class MyDate {
 int year; int month; int day; // int 형은 초기값이 0 이다.
}
public class Ex01 {
 static void changeInt(int y){
  y+=5;
 }
 static void changeRef(MyDate ref){
  ref.day+=5;
 }
 static MyDate createObject(MyDate ref) {
  ref=new MyDate();
  return ref;
 }
 public static void main(String[] args) {
  int x=10;
  MyDate d=new MyDate();
  for(int i=0;i<5;i++){
   changeInt(x); // main 지역 변수 x를 changInt 메소드에 입력 시켜서 y 값이 증가하지만
        // 출력 되는 값은 지역변수 설정값에 적용 시키지 못한다.
   changeRef(d); // MyDate형의 ref 변수에 레퍼런스 d의 초기값 0/0/0을 대입하고
        // day에 5를 더하여 그 값을 간직하고 있다. <- 이 말이 맞는 말인가???
   System.out.println(x);
   System.out.println(d.year + " : " + d.month + " : " + d.day );
  }
  System.out.println("=====================================");
 
  MyDate t; // 새로운 레퍼런스 t를 만든다
  t=createObject(d); // createObject메소드에 d의 값을 입력하여 t 값을 생성하지만
         // t는 기존의 실매개변수 0/0/0 을 받아서 ref에 저장하고 t로 리턴한다.
  System.out.println("1 " + d.year + " : " + d.month + " : " + d.day );
  System.out.println("2 "  + t.year + " : " + t.month + " : " + t.day );
 
  d.year=2007; d.month=7; d.day=19;
  System.out.println("3 " + d.year + " : " + d.month + " : " + d.day );
  System.out.println("4 "  + t.year + " : " + t.month + " : " + t.day );
 
  t.year=2008; t.month=8; t.day=6;
  System.out.println("5 " + d.year + " : " + d.month + " : " + d.day );
  System.out.println("6 "  + t.year + " : " + t.month + " : " + t.day );
 
  t=createObject(d);
  System.out.println("7 " + d.year + " : " + d.month + " : " + d.day );
  System.out.println("8 "  + t.year + " : " + t.month + " : " + t.day );
 }
}

2008. 8. 5. 16:33

Part2. 메소드 나머지 부분 & Part 3. 클래스와 객체(11. 클래스와 객체)

자바 클래스 선언하기

class 클래스 이름 {
  접근 지정자, 자료형, 변수;
  접근 지정자, 생성자() {
  ...
  }
  접근 지정자, 자료형, 메서드 이름() {
  ...
  }

// 절대값 구하기
package training;
public class Ex01 {
 static int compare(int a){
  //int abs;
  if(a<0){
   a=-a;
  }
   return a;
   // 함수를 호출해 준 곳으로 결과값으로 구한 절대값을 되돌려준다.
   //System.out.println(a);
 }
 public static void main(String[] args) {
  int a=-5; // 지역변수
  System.out.println("compare(a) : " + compare(a));
 }
}

// 1부터 입력 받은 수 까지의 자연수의 합을 구하시오.
// 입력 받은 수의 팩토리알을 구하시오.
package training;
public class Ex03 {
 static int sum(int n){
  int total=0;
  for(int i=1;i<=n;i++){
   total+=i;
  }
  return total;
 }
 static int fac(int m){
  int total=1;
  for(int i=1;i<=m;i++){
   total*=i;
  }
  return total;
 }
 public static void main(String[] args) {
  int n=Integer.parseInt(args[0]);
  System.out.println(" total =" + sum(n));
  System.out.println(" fac =" + fac(5));
 }
}

접근 지정자 :

// 객체 설명
package training;
// 새로운 자료형을 설계 -> 객체(인스턴스변수를 찍어 내기위한 틀)
class Animal{  // 클래스 내부에 멤버를 정의
    // 변수 형태의 속성 : 단순히 값을 저장하는 용도로 사용된다.
 private String name;
 // 캡슐화는 속성에 합당한 값만 저장할 수 있도록 하기 위해서 속성을
 // 외부에서 접근 못하도록 하고 대신 메소드로 접근하도록 한다.
 private int age;  // 접근 지정자 private은 해당 멤버를
                       // 자신의 클래스내의 메소드에서만 사용가능
 public String getName(){ // 속성값을 얻어옴(getter)
  return name;
 }
 public void setName(String new_name){ // 속성을 새로운 값으로 설정(setter)
  name=new_name;
 }
 public int getAge(){ // 속성값을 얻어옴(getter)
  return age;
 }
 public void setAge(int new_age){ // 속성을 새로운 값으로 설정(setter)
  if(new_age>=0)
  age=new_age;
 }
}
public class Ex04 {
 public static void main(String[] args) {
  // 클래스로 선언된 변수는 레퍼런스 변수로 실질적으로
  // 값을 저장할 공간을 마련하지 못한다. -> 실체를 참조하는 용도로 쓰인다.
  Animal a; // a는 선언 시, 기술한 자료형에 의해 형태가 결정된다.
  // 클래스로 실질적인 값을 저장할 공간을 마련하기 위해서는
  // new 연산자를 사용한다.
  // 힙영역에 생성된 실체는 이름이 없지만
  // new 연산자가 메모리 할당 후, 그 메모리의 위치정보를 되돌려 주면
  // 그 위치정보를 레퍼런스변수에 저장해야만 이 실체에 접근할 수 있다.
  a=new Animal();
  // 객체를 멤버 단위로 접근해서 사용함 : 멤버 참조 닷 연산자
  a.setName("사자"); //="원숭이"; // Animal 객체의 이름을 설정한다.
  a.setAge(26);
  // a.age=-26; // Animal 객체의 나이를 설정한다. // 속성을 새로운 값으로 설정
  // 이름하고 나이를 출력
  System.out.println(a.getName() + " , " + a.getAge()); // 속성값을 얻어옴
  // Animal 객체를 하나더 생성하여
  // 레퍼런스 변수 b로 접근하도록 하고
  // 이름은 "펭귄" 나이는 12로 저장하고 출력
  /*Animal b = new Animal();
  b.name="펭귄";
  b.age=12;
  System.out.println(b.name + "," + b.age);*/
 }
}

// int x를 private로 바꿨을 때 출력하기 위한 작업을 하시오.
package training;
class Thing{
 private int x;

 public int getX() {
  return x;
 }

 public void setX(int x) {
  this.x = x;
 }
}
public class Ex05 {
 public static void main(String[] args) {
  Thing thing = new Thing();
  thing.setX(10); //=10;
  System.out.println("x : " + thing.getX());
 }
}

// 속성으로 자판기에서 취급하는 제품의 정보를 저장하는 변수와 이를 다루기 위한 메소드를 갖는 자판기 클래스를 선언하고
// 다음과 같은 결과가 나오도록 객체 생성 후 메소드를 호출하시오.
// 복습할 때 모듈화를 시키시오.
// name, price를 private로 지정하고 출력할 수 있는 작업을 하시오.
package training;
class Product{
 private String name;
 private int price;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public int getPrice() {
  return price;
 }
 public void setPrice(int price) {
  this.price = price;
 }
 
}
public class Ex06 {
 public static void main(String[] args) {
  /* Product a = new Product();
  a.name="커피";
  a.price=500;
  Product b = new Product();
  b.name="웰치스";
  b.price=700;
  Product c = new Product();
  c.name="포카리";
  c.price=500;
  Product d = new Product();
  d.name="비타500";
  d.price=500;
  for(int i=1;i<=4;i++)
  // System.out.println(a[i].name + ":" + a[i].price + "원");
  System.out.println(a.name + ":" + a.price + "원");
  System.out.println(b.name + ":" + b.price + "원");
  System.out.println(c.name + ":" + c.price + "원");
  System.out.println(d.name + ":" + d.price + "원"); */
 
  // 레퍼런스 변수가 4개 필요
  Product [] a= new Product[4]; // 레퍼런스 값 4개 저장되는 배열
  // 인스턴스 4개 생성해서 레퍼런스 변수가 가리키도록 해야 함
  for(int i=0;i<a.length;i++){
   a[i] = new Product();
  }
   a[0].setName("커피") ; a[0].setPrice(150);
   a[0].setName("웰치스") ; a[0].setPrice(700);
   a[0].setName("포카리") ; a[0].setPrice(500);
   a[0].setName("비타500") ; a[0].setPrice(500);
   for(int i=0;i<a.length;i++){
    System.out.println(a[i].getName() + " , " + a[i].getPrice());
   }
 
 }
}

'수업 > 자바2JDK입문' 카테고리의 다른 글

Part 4. 상속 I  (0) 2008.08.08
Part 3. static  (2) 2008.08.07
Part 3. 생성자  (0) 2008.08.07
Part 2 & 3 메소드와 클래스  (0) 2008.08.06
PART 2(7 제어문의 다양한 활용 ~ 10 사용자정의 메서드 만들기)  (0) 2008.08.04
2008. 8. 5. 15:19

너네 공부하는 그룹 말이야~



스프링 노트의 그룹 노트를 쓰든,
티스토리의 팀블로그를 쓰든
카페를 만들든

그런 공간 있은 것이 좋을 것 같아~ ^^
2008. 8. 4. 15:37

PART 2(7 제어문의 다양한 활용 ~ 10 사용자정의 메서드 만들기)

7. 제어문의 다양한 활용
for문에 if문 사용하기
형식 :
for(초기값 ; 조건식 ; 증감식) {
  if(조건식)
  else
}
for문 안에 for문을 기술하는 다중for문
for(초기식 ; 조건식 ; 증감식) {
  실행문 ;
  for(초기식 ; 조건식 ; 증감식) {
    실행문 ;
  }
  실행문;
}
실행문;

문제 이렇게 출력되도록 프로그램을 짜 보시오
  1 
 234
56789

8. 제어문을 보조하는 보조제어문
실행을 중지하는 break 보조 제어문
반복문 -1 {
  반복문 -2 {
    break;             <= break 문이 실행되면
  }
}                        <= 반복문 -1 로 올라가서 다시 실행된다.

반복문 -1 위로 벗어나기 위해서는 레이블을 사용한다.
exit_for :                         <= 레이블 문에서 다시 시작한다.
반복문 -1 {
  반복문 -2 {
    break exit_for;             <= 레이블이 실행되면
  }
}                        

continue 보조 제어문
break 문은 완전히 반복문을 벗어나지만 continue문은 반복을 계속하기 위해 증감식으로 제어가 옮겨짐.
반복문 {         <- 반복문의 증감식으로 올라온다.
  :
  :
  continue;     <- continue 문을 만나면
  :
  :
}

9. 배열

1차원 배열 선언의 형식
1. new 연산자를 이용하는 방법
ex : int [] a = new int [5];
a : 배열의 이름, int : 배열에 들어갈 자료형, [5] : 배열에 들어갈 원소의 개수
2. 해당 배열의 내용을 직접 초기화하는 방법
ex : int [] a = { 10, 20, 30, 40, 50 };

다차원 배열
예제 1.
int [] [] a = new int [3] [5]; // 3행 5열의 경우

score[0][0]=10; score[0][1]=90; score[0][2]=70;

score[1][0]=60; score[1][1]=80; score[1][2]=65;

score[2][0]=55; score[2][1]=60; score[2][2]=85;

score[3][0]=90; score[3][1]=75; score[3][2]=95;

score[4][0]=60; score[4][1]=30; score[4][2]=80;

예제 2.
int [][]score = { { 85, 60, 70}, //0 행

                        { 90, 95, 80}, //1 행

                        { 75, 80, 100}, //2 행

                        { 80, 70, 95}, //3 행

                        {100, 65, 80} //4 행

                     };

010: int [] subject = new int[3]; //각 과목별 총점을 저장할 변수 선언

011: int [] student = new int[5]; //각 학생별 총점을 저장할 변수 선언

10. 메서드와 자바 프로그램
모듈화 프로그래밍이란?
프로그래머가 한번에 생각할 수 있는 단위로 모듈화하여 프로그래밍을 할 경우, 프로그램을 작성하기가 쉬워지고 디버깅이 용이하므로 프로그램을 기능별로 모듈화하기 위해서 메서드가 사용되는데 이를 사용자 정의 메서드라고 하며 적절한 곳에서 호출해서 사용할 수 있다.

사용자 정의 메서드 만들기
자료형 메서드이름 (전달인자리스트) {
  변수 선언 ;
  문장 ;
  return (결과 값); // 메서드의 자료형과 리턴값의 자료형은 일치해야 한다.
}

void형 메서드
메서드의 몸체에서 기술한 명령을 실행할 뿐 메서드의 리턴값을 받지 않는 경우 void라는 자료형을 사용한다.

질의 사항
지역 변수와 전역 변수의 차이는???
아래는 main 메서드의 지역변수를 prn메서드에서 불러와서 쓰는 경우인데
지역변수는 정의한 메서드에서만 사용할 수 있다고 했는데
왜 prn 메서드에서 정상적인 호출이 가능한 것인지.
그리고 전역변수로 어떻게 지정하는지...
prn 메서드 내부에서 정의 내리면 왜 컴파일 에러가 나는지...

// char ch = '#'
// int n=5;
// ch에 저장된 문자를 n 개수만큼 반복 출력
package training;
public class Ex14 {
 // char ch='#';
 static void prn(char ch, int n){
  // char ch='#';
  for(int i=0;i<n;i++)
  System.out.print(ch+" ");  
 }
 public static void main(String[] args) {
  char ch='#';
  prn(ch,10);
  prn('@',5);
 
 }

}

'수업 > 자바2JDK입문' 카테고리의 다른 글

Part 4. 상속 I  (0) 2008.08.08
Part 3. static  (2) 2008.08.07
Part 3. 생성자  (0) 2008.08.07
Part 2 & 3 메소드와 클래스  (0) 2008.08.06
Part2. 메소드 나머지 부분 & Part 3. 클래스와 객체(11. 클래스와 객체)  (3) 2008.08.05
2008. 8. 4. 12:34

참고할 만한 스크린 캐스트 및 강의

이클립스 유로파로 시간을 절약하는 열 가지 기법( 제목은 유로파 이지만, 유로파 이후 버전을 사용하는 법 또는 이클립스를 어떻게 이용하면 좋은지에 대한 좋은 기법을 보여준다 할 수 있다 ) - 향후 살펴보기 바람

:http://www.ibm.com/developerworks/kr/library/tutorial/screencast/20080722/

2008. 8. 3. 01:40

자바 공부에 좋은 사이트 1

javachobo.com

에 가면 소스를 내려 받을 수도 있고 강의 동영상 내려 받을 수도 있다.

좋은 자료야..

잘 보고~~

또 플래쉬로 된 자바의 메모리 구조나 이런 것들은 그 카페에 공유 되어 있으니 참조 바람~

그럼 수고~
2008. 8. 2. 23:10

글이 안올라오네 ㅋㅋㅋ

숙제 검사 하러 왔더니 글이 안올라오네.~~

바뿌남?
2008. 7. 27. 23:42

이클립스 유로파 버전 스크린캐스트

2008. 7. 24. 00:13

chapter 8. 인터페이스와 추상 클래스

다형성을 제대로 사용하려면 100% 추상클래스인 인터페이스가 필요하다.
추상 클래스(abstract class)란 인스턴스를 만들 수 없는 클래스이다.

클래스를 추상 클래스로 만드는 방법은 클래스를 선언할 때 앞에 abstract 만 붙여주면 된다.
abstract class Canine extends Animal {
    public void roam() {
    }
}
추상 클래스란, 아무도 그 클래스의 새로운 인스턴스를 만들 수 없는 클래스를 의미한다.

abstract class Canine extends Animal {
    public void roam() {
    }
}
==============================================================
public class MakeCanine {
    public void go() {
        Canine c;           <- 상위클래스가 추상클래스인 경우에도 하위클래스 객체를 상위클래스 레퍼런스에
        c = new Dog();        대입하는 것은 가능하기 때문에 이 부분은 문제가 없다
        c = new Canine(); <- Canine 클래스는 추상클래스기 때문에 컴파일시 에러가 난다.
        c.roam();
    }
}

추상 클래스는 확장하지 않으면 쓸모가 없다.
추상 클래스를 만들었을 때 실제 실행 중에 일을 처리하는 것은 그 추상 클래스의 하위 클래스 인스턴스이다.
추상 클래스가 아닌 것을 구상클래스라고 한다. 상속트리의 맨 마지막 클래스들

추상 메소드
추상 클래스가 반드시 확장해야 하는 클래스라면 추상 메소드는 반드시 오버라이드 해야하는 메소드이다.
추상 메소드에는 몸통이 없다.
public abstract void eat();  <- 메소드 몸통이 없으므로 세미콜론으로 끝내면 된다.
추상 메소드를 만들 때는 클래스도 반드시 추상 클래스로 만들어야 한다.
추상 메소드를 만드는 이유는 실제 메소드 코드를 전혀 집어넣지는 않았더라도 일련의 하위클래스를 위한
규약(protocol)의 일부를 정의하기 위해서이다.
추상 메소드는 다형성을 활용하기 위해 "이 유형에 속하는 모든 하위클래스 유형에는 이 메소드가 있어야 한다"는
것을 지정하기 위해 필요하다.

"추상 메소드를 반드시 구현해야 한다"는 의미는 추상 메소드에서 선언한 리턴 유형과 호환가능한 리턴 유형을 가진 추상 메소드가 아닌 메소드를 만들어야 한다는 의미이다.

자바에서 모든 클래스는 Object라는 클래스를 확장한 것이다.
명시적으로 다른 클래스를 확장하지 않은 클래스는 자동으로 Object를 확장한 클래스로 정의됩니다.

Object 클래스를 대략 살펴보자.
equals(Object o) <- 두 객체를 '같은'것으로 볼 수 있을지 판단하는 메소드
getClass() <- 어떤 클래스의 인스턴스인지 알 수 있도록 그 객체의 클래스를 리턴한다.
hashCode() <- 그 객체에 해당하는 해시코드(고유 ID)를 출력한다.
toString() <- 클래스명과 몇가지 별로 잘 쓰이지 않는 숫자가 포함된 String 메시지 출력

Object를 추상 클래스로 선언하지 않는 이유는 모든 클래스에서 무조건 오버라이드할 필요 없이 그대로 사용할 수 있는 메소드를 구현해놓은 코드가 들어있기 때문이다.
Object 유형의 객체를 만들 수는 있지만, 실제로 그렇게 할 일은 별로 없다.
Object 클래스의 두가지 용도
1. 임의 클래스에 대해 어떤 작업을 하는 메소드를 만들 때 다형적 유형으로 사용하는 경우
2. 자바에 있는 모든 객체에서 실행 중에 필요한 진짜 메소드 코드를 제공하기 위해서

Object 유형의 다형적 레퍼런스를 쓸 때 나오는 객체(ArrayList<Object>)는 실제 객체의 유형이나 목록에 객체를 추가했을 때의 레퍼런스 유형하고는 상관 없이 무조건 Object 유형의 레퍼런스로 나오게 된다.

컴파일러에서 어떤 메소드를 호출할 수 있는지 결정할 때는 실제 객체 유형이 아닌 레퍼런스 유형을 기준으로 따진다.

ArrayList<Object>에 객체를 집어넣으면 그 객체는 원래의 유형과는 무관하게 Object로만 처리할 수 있다.
ArrayList<Object>로부터 레퍼런스를 받아오면 그 레퍼런스는 항상 Object유형입니다.

어떤 객체인지 모를 경우에는 instanceOf 연산자를 써서 확인한다.
if (d instanceOf Dog) {
    Dog d=(Dog) o;
컴파일러에서는 레퍼런스가 참조하는 실제 객체의 클래스가 아닌 레퍼런스 변수를 선언할 때 지정한 유형의 클래스를 확인하다.

인터페이스(interface)
인터페이스를 정의하려면 public interface Pet {...} <- class 대신에 interface 키워드를 사용한다.
인터페이스를 구현하려면 public class Dog extends Canine implements Pet {...} <- implements 뒤에 인터페이스 명을 지정해줍니다.

public interface Pet {
    public abstract void beFriendly() ;   <- 인터페이스에 들어있는 모든 메소드는 추상메소드므로 반드시
    public abstract void play() ;            <- 세미콜론으로 끝나야합니다.
}

서로 다른 상속 트리에 속한 클래스에서도 같은 인터페이스를 구현할 수 있습니다.
또한 한 클래스에서 인터페이스 여러 개를 구현할 수도 있습니다.

어떤 클래스를 하위클래스로 만들지, 추상 클래스로 만들지, 아니면 인터페이스로 만들지를 어떻게 결정하는가!
클래스를 새로 만들려고 할 때 그 클래스가 (Object를 제외) 다른 어떤 유형에 대해서도 'A는 B다' 테스트를 통과할 수 없다면 그냥 클래스를 만듭니다.
어떤 클래스의 더 구체적인 버전을 만들고 어떤 메소드를 오버라이드하거나 새로운 행동을 추가해야 한다면 하위클래스를 만듭니다(클래스를 확장합니다.)
일련의 하위클래스에서 사용할 틀(template)을 정의하고 싶다면, 그리고 모든 하위클래스에서 사용할 구현코드가 조금이라도 있다면 추상 클래스를 사용합니다. 그리고 그 유형의 객체를 절대 만들 수 없게 하고 싶다면 그 클래스를 추상 클래스로 만듭니다.
상속 트리에서의 위치에 상관없이 어떤 클래스의 역할을 정의하고 싶다면 인터페이스를 사용하면 됩니다.

핵심정리
1. 클래스를 만들 때 인스턴스를 만들 수 없게 하고 싶다면 abstract 키워드를 사용해서 추상 클래스로 만든다.
2. 추상 클래스에는 추상 메소드와 추상 메소드가 아닌 메소드 모두를 집어넣을 수 있다.
3. 클래스에 추상 메소드가 하나라도 있으면 그 클래스는 추상 클래스로 지정해야 한다.
4. 추상 메소드에는 본체가 없으며 선언 부분은 세미콜론으로 끝납니다(중괄호를 쓰지 않는다)
5. 상속 트리에서 처음으로 나오는 구상 클래스에서는 반드시 모든 추상 메소들르 구현해야 합니다
6. 자바에 들어있는 모든 클래스는 직접 또는 간접적으로 Object(java.lang.Object)의 하위클래스입니다.
7. 메소드를 선언할 때 인자, 리턴 유형을 Object로 지정해도 됩니다.
8. 어떤 객체에 대해서 메소드를 호출하려면 그 객체를 참조하는 레퍼런스 변수 유형의 클래스(또는 인터페이스)에 그 메소드가 있어야만 합니다. 객체의 실제 유형하고는 무관합니다. 따라서 Object 유형의 레퍼런스 변수로는 Object 클래스에 정의되어 있는 메소드만 호출할 수 있습니다. (레퍼런스가 참조하는 객체의 유형과는 무관)
9. Object 유형의 레퍼런스 변수는 캐스팅을 하지 않고는 다른 유형의 레퍼런스에 대입할 수 없습니다. 한 유형의 레퍼런스 변수를 하위 유형의 레퍼런스 변수에 대입하고 싶다면 캐스팅을 이용할 수 있습니다. 하지만 힙에 들어있는 객체가 캐스팅 호환 가능한 유형이 아니라면 실행 중에 캐스팅에 실패할 수도 있습니다.
10. 자바에서는 다중 상속을 허용하지 않습니다. 클래스는 단 하나만 확장할 수 있습니다. (직속 상위 클래스는 하나밖에 없다)
11. 인터페이스는 100% 추상 클래스이고 추상 메소드만 정의한다 정의는 interface로 하고 구현은 implements로 한다.
12. 클래스는 여러 개의 인터페이스를 구현할 수 있다.
13. 인터페이스의 모든 메소드는 자동으로 public 메소드, 그리고 abstract 메소드가 되기 때문에 인터페이스를 구현하는 클래스에서는 인터페이스에 들어있는 모든 메소드를 구현해야 한다.
14. 하위클래스에서 어떤 메소드를 오버라이드했는데, 상위클래스 버전을 호출하고 싶다면 super라는 키워드를 사용하면 된다. ex : super.runReport();
2008. 7. 22. 23:20

chapter 7. 상속과 다형성

상속이란 하위클래스가 상위클래스의 멤버(인스턴스 변수, 메소드)를 물려 받는 것
하위클래스는 별도의 메소드와 인스턴스 변수를 추가할 수 있고 상위클래스의 메소드를 오버라이드 할 수 있다.
그러나 인스턴스 변수는 오버라이드 하지 않는다. 인스턴스 변수가 특별한 행동을 정의하지 않기 때문에...

상속 트리의 설계
1. 공통적인 속성과 행동이 들어있는 객체를 찾는다.
2. 공통적인 상태와 행동을 나타내는 클래스를 설계한다.
3. 특정 하위클래스 유형에만 적용되는 행동(메소드 구현)이 필요한지 결정한다.
4. 공통적인 행동이 필요한 하위클래스를 두 개 이상 찾아서 추상화의 개념을 더 폭넓게 활용할 수 있는지 찾는다.
5. 클래스 계층 구조를 완성한다.

하위클래스에서 상위클래스에 있는 버전의 메소드와 새로 오버라이드한 버전의 메소드 둘 다 사용하고 싶을 경우에는 먼저 상속 받은 메소드를 실행시킨 후, 하위클래스에서만 실행할 메소드를 처리한다.

상속을 활용하여 설계할 때의 주의점
어떤 클래스가 다른 클래스(상위클래스)를 더 구체화한 형식이라면 상속을 활용한다.
같은 일반적인 형식에 속하는 여러 클래스에서 공유해야 하는 어떤 행동(구현된 코드)이 있다면 상속을 활용한다.
그러나 객체지향 프로그래밍에 있어서 상속의 핵심 기능 가운데 하나지만 행동을 재사용하는 데 있어 무조건 최선의 방법이 아니라는 점을 주의해야 한다.
상위클래스와 하위클래스 사이의 관계가 위에 있는  두 가지 규칙에 위배된다면 어떤 코드를 다른 클래스에서
재사용할 수 있다는 이유만으로 상속을 사용하면 안된다.
하위클래스와 상위클래스 사이에서 'A는 B이다' 관계가 성립하지 않는다면 상속을 사용하지 않는다.

상속의 주요 특징
자바에서는 하위클래스가 상위클래스를 확장한다고 한다.
하위클래스는 상위클래스에 있는 모든 public으로 지정한 인스턴스 변수와 메소드를 상속하지만 private로 지정한 인스턴스 변수와 메소드는 상속하지 않는다.
메소드는 오버라이드 가능하지만 인스턴스 변수는 오버라이드 하지 않는다.
'A는 B이다' 라는 관계를 확인한다.(한방향으로만 작동한다.)
하위클래스에서 메소드를 오버라이드하고 하위클래스의 인스턴스 변수에 대해 그 메소드를 호출하면 오버라이드된 버전의 메소드가 호출된다.(맨 밑에 있는것이 호출 됨)
B라는 클래스가 A라는 클래스를 확장하고 C는 B를 확장한다면 클래스 B는 클래스 A이고 클래스 C는 클래스 B이고 클래스 C는 클래스 A이다.

상속의 장점
코드가 중복되는 것을 방지할 수 있다.
(그러나 특정 메소드의 인자나 리턴 형식, 메소드명과 같이 상위클래스에 있는 것 가운데 하위클래스에서 반드시 필요로 하는 것을 변경하면 심각한 문제가 생길 수 있다.)
일련의 클래스를 위한 공통적인 규약(protocol)를 정의할 수 있다.

다형성의 이해
객체 선언과 대입의 세 가지 단계
Dog myDog = new Dog();
    1.          2.      3.
1. 레퍼런스 변수를 선언한다.
2. 객체를 만든다.
3. 객체와 레퍼런스를 연결한다.
주요사항은 레퍼런스 유형과 객체 유형이 똑같아야 한다는 점이다.

하지만 다형성을 활용하면 레퍼런스와 객체가 다른 유형이어도 됩니다.
Animal myDog = new Dog();

다형성을 사용하면 레퍼런스 유형을 실제 객체 유형의 상위클래스 유형으로 지정할 수 있다.

Animal[] animals = new Animal[5];
animals [0] = new Dog();
animals [1] = new Cat();
animals [2] = new Wolf();
animals [3] = new Hippo();
animals [4] = new Lion();

for (int i = 0 ; i < animals.length ; i++ ) {
  animals[i].eat();
  animals[i].roam();

의문사항
인자와 리턴 유형에 대해서도 다형성을 적용할 수 있다.


대부분의 상속계층은 넓지만 깊지는 않다.
클래스의 소스코드를 직접 접근할 수 없지만 어떤 클래스의 메소드가 작동하는 방식을 바꾸고 싶을 때는 클래스를 확장한 후 메소드를 오버라이드해서 더 나은 코드를 만들면 된다.
상속이 안되는 경우.
클래스를 private로 지정할 경우
클래스를 final로 지정할 경우
내부 클래스(inner class)인 경우
오버라이드할 수 없도록 만들고 싶은 경우에는 final 클래스를 사용한다.

상위클래스의 메소드를 오버라이드할 때이 규칙
1. 인자는 동일해야 하고, 리턴 유형은 호환 가능해야 한다.
2. 메소드를 더 접근하기 어렵게 만들면 안된다(public 메소드를 오버라이드해서 private 메소드를 만드는 등등)

메소드 오버로딩이란 이름이 같고 인자 목록이 다른 메소드 두 개를 만드는 것.
오버로딩을 활용하면 호출하는 쪽의 편의를 위해 같은 메소드를 서로 다른 인자 목록을 가진 여러 버전으로 만들 수 있다. 오버로드하는 메소드에서는 상위클래스에서 정의한 다형성 계약을 이행하지 않아도 되기 때문에 메소드 오버로딩은 훨씬 더 융통성이 좋다고 할 수 있다.
규칙 & 장점
1. 리턴 유형이 달라도 된다.
2. 리턴 유형만 바꿀 수는 없다.(인자 목록을 반드시 변경해야 한다.)
3. 접근 단계를 마음대로 바꿀 수 있다.