ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 객체의 행동
    Programming/JAVA 2010. 5. 3. 08:02

    •   상태는 행동에 영향을 끼치고 행동은 상태에 영향을 끼칩니다.

    객체에는 각각 인스턴스 변스와 메소드로 표현되는 상태와 행동이 있습니다.

    객체에는 상태에 대해 어떤 작업을 처리할 수 있는 행동(behavior)라는 것이 있습니다. 즉 메소드에서는 인스턴스 변수의 값을 사용합니다.

     

    잊지마세요: 클래스에서는 객체가 아는 것과 객체가 하는 것을 기술합니다.

    클래스는 객체에 대한 청사진 입니다.

     

    같은 유형에 속하는 모든 객체들이 서로 다른 행동을 하는 메소드를 가질 수 있을 까요?

    특정클래스의 모든 인스턴스에 들어있는 메소드 자체는 똑같지만 메소드의 행동은 인스턴스 변수의 값에 따라 달라질 수 있습니다.

     void play(){

    soundPlayer.playSound(title);                                     

    }

    Song t2 = new Song();

    t2.setArtist("Travis");

    t2.setTitle("Sing");

    Song s3 = new Song();

    s3.setArtist("Sex Pistols");

    s3.setTitle("My Way");

     1.11.JPG

     

     

    메소드에 뭐가를 보낼수도 있습니다

    메소드에서 사용하는 것은 매개변수. 호출하는 쪽에서 전달하는 것인 인자라 부릅니다.

    한 가지 중요한 점이 있는데요. 그것은 메소드에서 매개변수를 받도록 선언했다면 그 메소드를 사용할 때 반드시 뭔가를 전달해야 합니다.

    그리고 그 '뭔가' 는 반드시 정해진 유형의 값이어야 합니다.

     

    Dog d = new Dog();                               Dog 레퍼런스의 bark 메소드를 호출하는데, 이때 3이라는 겂을 전달합니다.

    d.bark(3);     //인자를 받아서                   bark 메소드에서는 3을 나타내는 비트들이 전달됩니다

     

    void bard(int numOfBarks) {                   그 비트들은 numOfBarks 매개변수(int 크기의 변수)에 들어갑니다

    while(numOfbarks > 0){                   그 numOfBarks 매개변수는 메소드 코드 내에서 변수로 쓰입니다

    System.out.println("ruff");          

    numOfBarks =  numOfBarks -1;

    }

    }

     

    메소드에서 뭔가를 돌려받을 수도 있습니다

    메소드를 선언할 때 어떤 값을 리턴하겠다고 선언했다면 반드시 그렇게 선언한 유형의 값을 리턴해야 합니다.(또는 선언한 유형과 호환 가능한 값을 리턴 할 수도 있습니다.)

    뭔가를 돌려주기로 약속했다면 반드시 돌려주는 것이 좋습니다.

    int theSecret = life.giveSecret();           int라는 유형은 반드시 같아야합니다.

    int giveSecret(){                                giveSecret()메소드에서는 42를 나타내는 비트들을 리턴하며, 그 값이 theSecret라는 이름을 가진 변수로 들어갑니다.

    return 42;          <===  이건 int에 들어갈 수 있는 값이어야 합니다.

    }

     

    메소드에 인자 두 개 이상을 전달할 수도 있습니다.

    메소드에 매개변수 여러개가 있을 수도 있습니다. 이렇게 매개변수 여러 개가 필요하다면 선언할 때 각 매개변수를 쉼표로 구분해서 쓰면 됩니다.

    인자를 전달 할 때도 각 인자를 쉼표로 구분하면 됩니다.

    가장 중요한 것은 메소드에 매개변수가 있을 때 그 유형과 순서를 정확하게 맞춰서 전달 해야한다는 것입니다.

     

    매개변수 두 개가 있는 메소드를 호출하면서 인자 두 개를 보낼 때

    void go{

    TestStuff t = new TestStuff();

    t.takeTwo(12,34);                       이렇게 인자 두 개를 보내면 그 두 인자는 보낸 순서대로 매개변수로 들어갑니다.

    }                                                    첫번째인자는 첫번째 매개변수에, 두 번째 인자는 두 번째 매개변수에 들어가는식으로 말이죠.

    void go2{

    int foo = 7;                                 foo와 bar의 값은 x와 y의 매개변수로 들어값니다.

    int bar = 3;

    t.takeTwo(foo,bar);

    }

    void takeTwo(int x, int y) {

    int z = x + y;

    System.out.println("Total is" + z);

    }

     

    자바에서는 값으로 전달합니다. 즉, 복사본을 전달하는 것이지요.

    int x = 7;

    int 변수를 선언하고 거기에 '7'이라는 값을 대입합니다. 그러면 7에 해당하는 비트 패턴이 x라는 이름의 변수에 들어갑니다.

     

    void go(int z){}

    z라는 이름의 int 매개변수가 있는 메소드를 선언합니다.

     

    foo.go(x);    void go(int z){}

    go()메소드를 호출할때 x변수를 인자로 전달합니다. x에 들어있는 비트들이 복사되며 그 복사본은 z로 들어갑니다.

     

    void go(int z){         메소드 안에 있는 z의 값을 바꿉니다.

    z=0;                  x의 값은 바뀌지 않아요 매개변수로 전달된 인자는 x의 복사본 이니까요.

    }                           

     

    매개변수와 리턴 유형 활용방법

    가장 대표적인 것은 게터(getter) 와 세터(setter) 입니다. 정식 명칭은 엑세서(accessor) 와 뮤테이터(mutator)입니다.

    게터와 세터는 각각 어떤 것을 가져오고(get) 설정하는(set) 역할을 합니다.

    보통 인스턴스 변수의 값에 대해  게터는 가져오기로 되어있는 값을 리턴값 형태로 받아오기 위한 용도로만 사용되며,

    세터는 성정할 값을 인자로 받아서 인스턴스 변수를 그 값으로 설정하기 위한 용도로 쓰입니다.

     

    class ElectricGuiter{

    String braand;

    int numOfPickups;

    boolean rockStarUsesIt;

     

    String getBrand(){

    return brand;

    }

    void setBrand(String aBracd) {

    this.brand = aBrand;

    }

    Int getNumOfPickups(){

    return numOfPickups;

    }

    void setNumOfPickups(Int num) {

    this.numOfPickups= num;

    }

    String getRockStarUsesIt(){

    return rockStarUsesIt;

    }

    void setRockStarUsesIt(Boolean YesOrNo) {

    this.rockStarUsesIt= YesOrNo;

    }

    }

     

    캡슐화

    데이터를 어떻게 해야 숨길 수 있을까요?? 바로 public 과 private라는 접근 변경자를 사용하면 됩니다.

    public은 그리 낯설지 않을 것입니다. 모든 main메소드 앞에는 public 라는 변경자가 붙으니까요.

    캡슐화를 하려면 인스턴스 변수를 private로 지정하고 접근 제어를 위해 public 으로 지정된 게터와 세터를 만들면 됩니다.

     세터에서 가장 중요한 점은 나중에 뭔가를 변경하더라도 다른 코드는 건드리지 않아도 된다는 점입니다.(게터에서도 마찬가지)

     

    배열에 있는 객체는 어떤 식으로 행동할까요?

    다른 객체와 동일합니다. 접근하는 방법이 조금 다를 뿐이죠.

    즉 리모컨의 사용법이 조금 다르다고 생각하면 됩니다

     

    1.Dog 레퍼런스 일곱 개를 담을 수 있는 Dog배열을 선언하고 생성합니다.

    Dog[] pets;

    pets = new Dog[7];

     

    2.Dog객체 두 개를 새로 만들고 첫번째와 두 번째 배열 원소에 대입합니다.

    pets[0] = new Dog();

    pets[1] = new Dog();

     

    3.Dog 객체 두 개에 대해 메소드를 호출합니다.

    pets[0].setSize(30);

    int x = pets[0].getSize();

    pets[1].setSize(8);

     

    인스턴스 변수 선언과 초기화

    인스턴스 변수를 무조건 초기화 할 필요는 없습니다.

    항상 어떤 기본값으로 설정되기 때문이죠. 숫자 원시 변수(char 포함)는 0, 부울형은 false, 객체 레퍼런스는 null이라는 기본 초기값이 있습니다.

    인스턴스 변수에는 항상 어떤 기본값이 들어갑니다.

    인스턴스 변수에 직접 어떤 값을 대입하거나 세터 메소드를 호출하지 않은 경우에도 그 인스턴스 변수에는 기본값이 들어있습니다.

    정수  0   ,   부동소수점수  0.0   ,   부울  false  ,   레퍼런스  null

     

    인스턴스 변수와 지역 변수의 차이점

    • 지역변수에는 기본값이 없습니다. 따라서 지역 변수를 초기화하기 전에 사용하려고 하면 컴파일 과정에서 오류가 납니다.

      1. 인스턴스 변수는 클래스 내에서 선언됩니다. 메소드 내에서 선언되는 것이 아닙니다.

        class Horse{

        private double height = 15.2;

        private String breed;

        //나머지 코드

        }

      2. 지역변수(local variable) 는 메소드 내에서 선언됩니다.

        class AddThing{

        int a;

        int b=12;

        public int add(){

        int total = a+b;

        return total;

        }

        }

      3. 지역 변수는 사용하기 전에 반드시 초기화해야합니다.

        class Foo{

        public void go(){

        int x;

        int z = x + 3;        컴파일이 되지 않습니다. x를 선언할 때 아무 값도 지정하지 않아도 되긴 하지만 그렇게 값이 선언되지 않은

        }                              값을 사용하려고 하면 컴파일 할때 오류가 납니다.

        }

     

    ※ 메소드 매개변수는 지역변수와 거의 같습니다. 메소드 내에서 선언되죠(정확하게 말하자면 메소드 본체 내에서라기보다는 메소드의 인자 목록(argument list)내에서 선언됩니다.하지만 그래도 인스턴스 변수는 아니고 지역 변수 입니다.)

    메소드 매개변수는 절대 초기화 되었던 것이 해제되는 일이 없기 때문에 컴파일러에서 매개변수가 초기화되지 않았을수 있다는 오류 메시지가 나오는 일은 일어나지 않습니다.

    그러나 메소드를 호출할 때 메소드에서 필요로 하는 인자를 전달하지 않으면 컴파일할 때 오류가 나지요, 따라서 매개변수는 항상 초기화 됩니다. 컴파일러에서는 메소드를 호출할 ,

    메소드를 선언할 때 지정한 것과 같은 인자를 전달했는지 그리고 매개변수에 (자동으로 )인자가 대입되었는지 반드시 확인하기 때문이지요.

     1.112.JPG

    변수(원시 변수와 레퍼런스 비교)

    두 원시값을 비교 할 때는 == 연산자를 씁니다.

    레퍼런스 두 개가 똑같은지(즉 힙에 들어있는 똑같은 객체를 참조하는지) 확인할 때도 == 연산자를 쓸수 있습니다.

    == 연산자는 변수에 들어있는 비트들의 패턴을 비교하는 역할을 합니다.

     int a=3;                                                              

    byte b=3;

    if( a == b ) { // 참 }

    원시 유형 두개를 비교하거나 레퍼런스 두 개가 같은 객체를 참조하고 있는지 알고 싶다면 ==  를 쓰면 됩니다.

    서로 다른 두 객체가 똑같은지 알고 싶을 때는 equals() 메소드를 사용하면 됩니다.

    예를 들어, 서로 다른 String 객체가 모두"Fred"라는 문자열을 나태내는 것인지 확인하고 싶다면 이 메소드를 쓰면 됩니다.

    Foo a = new Foo();1.113.JPG

    Foo b = new Foo();

    Foo c = a;

    if( a == b ) { // 거짓 }  

    if( a == c ) { // 참 }

    if( b == c ) { // 거짓 }

     

    핵심정리

    • 클래스에서는 객체가 아는 것과 객체가 하는 것을 정의합니다.
    • 인스턴스 변수(상태)는 객체가 아는 것입니다.
    • 메소드(행동)는 객체가 하는 것입니다.
    • 메소드에서 인스턴스 변수를 이용하여 같은 유형의 객체가 다른 식으로 행동하게 할수 있습니다.
    • 전달하는 값의 개수와 유형은 반드시 메소드를 선언할 때 지정한 것과 같아야 하며 그 순서도 같아야 합니다.
    • 메소드 안팎으로 전달되는 값은 상황에 따라 자동으로 더 큰 유형으로 올라갈 수 있습니다. 더 작은 유형으로 바꿔야 한다면 강제로 캐스팅을 해야합니다.
    • 메소드에 인자를 전달할 때는 리터럴값(2,'c' 등)을 사용할 수도 있고 선언된 매개변수 유형의 변수를 사용할 수도 있습니다.
    • 메소드를 선언할 때 반드시 리턴유형을 지정해야 합니다. 리턴유형을 void로 지정하면 아무것도 리턴하지 않아도 됩니다.
    • 메소드를 선언할 때 void가 아닌 리턴 유형을 지정했을 때는 반드시 선언된 리턴 유형과 호환 가능한 값을 리턴해야 합니다.

     

     

     

     

     

     

     

    'Programming > JAVA' 카테고리의 다른 글

    JDBC API 를 이용한 프로그래밍.  (0) 2010.05.03
    클래스와 객체  (0) 2010.05.03
    자바를 소개합니다. ^^  (0) 2010.05.03
    원시 변수와 레퍼런스  (0) 2010.05.03
    메소드를 더 강력하게  (0) 2010.05.03
Designed by Tistory.