ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 7. 객체지향 2. 아들아 물려주마.
    Programming/JAVA 2010. 5. 3. 21:03

    1.상속
    1.1 상속의 정의와 장점

    상속이란?

    기존의 클래스를 재활용하여 새로운 클래스를 만드는 것

    효과

    보다 적은 양의 코드로 새로운 클래스를 작성이 가능하다

    코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.

    상속을 하는 방법 : extends

    상속을 하기 위해 사용하는 keyword는 바로 extends이다.

    예 : class Child extends Father{ … }

    Child와 Father 클래스는 서로 상속관계에 있다라고 하며

    상속해주는 Father를 조상클래스, super class, base class라고 하고

    상속받는 Child를 자식클래스, sub class, derived class라고 한다.
    1.1 상속의 정의와 장점

    상속관계

    Child와 Father와의 관계를 보통은 이렇게 표현한다.

    그러나 이렇게 도식화 하면 이해가 더 편하다.
    Father
    Child
    Father
    Child
    1.1 상속의 정의와 장점

    상속관계

    만일 Father class에 age라는 정수형 변수를 추가하면 Child는 자연스레 age라는 멤버변수를 추가하게 된 것과 같 은 효과를 가진다.

    이제 Child class에 play()라는 메서드를 추가하겠다.
    age
    Child
    Father
    age
    play()
    Child
    Father
    1.1 상속의 정의와 장점

    상속관계

    상위클래스인 Father에 멤버가 추가되면 자식은 당장 영향 을 받는다.

    반면 자식클래스인 Child에 새로운 멤버가 추가되어도 상위 클래스인 Father는 아무런 영향을 받지 않는다.

    자식클래스는 조상클래스의 모든 멤버를 상속받으므로 항상 조상클래스보다 같거나 많은 멤버를 갖는다.

    즉, 상속에 상속을 거듭할 수록 상속받는 클래스의 멤버의 개수는 점점 늘어나게 된다.

    그래서 상속의 키워드가 확장의 의미를 가진 extends라고 해석이 가능하다.
    1.1 상속의 정의와 장점

    상속관계 : 주의할 점

    생성자와 초기화 블록은 상속되지 않는다

    멤버만 상속된다

    자손클래스의 멤버 개수는 조상클래스보다 항상 같거나 많다
    1.1 상속의 정의와 장점

    상속관계

    이번엔 Father 클래스의 상속을 받는 Child2라는 클래스가 추가되었다.

    class Father{…}

    class Child extends Father{…}

    class Child2 extends Father{…}
    Father
    Child
    Child2
    1.1 상속의 정의와 장점

    상속관계

    Child, Child2는 모두 Father 클래스를 상속받는다

    그러나 주의해야 할 것은 Child와 Child2는 아무런 관계가 없다.

    클래스간의 관계에서는 오로지 상속관계만 존재한다.

    클래스간 형제관계는 없다.

    그래서 Child와 Child2에 추가해야 할 멤버가 있다면 Father에 추가하는 것이 더 적절하다.

    이렇게 되면 Father 클래스 하나만 변경하면 되기 때문에 작업이 간단해 진다.

    더더군다나 같은 내용의 코드를 한쪽에 관리함으로써 코드의 중복이 줄어든다는 점이다.
    1.1 상속의 정의와 장점

    예제
    class Tv{
    boolean power; // 전원상태(on/off)
    int channel; // 채널
    void power() { power = !power; }
    void channelUp() { ++channel; }
    void channelDown() { --channel;}
    }
    class CaptionTvextends Tv{
    boolean caption; // 캡션상태(on/off)
    void displayCaption(Stringtext) {
    if (caption) { // 캡션상태가on(true)일때만text를보여준다.
    System.out.println(text);
    }
    }
    }
    1.1 상속의 정의와 장점

    예제(계속)
    class CaptionTvTest{
    public static void main(Stringargs[]) {
    CaptionTvctv= new CaptionTv();
    ctv.channel= 10; // 조상클래스로부터상속받은멤버
    ctv.channelUp();// 조상클래스로부터상속받은멤버
    System.out.println(ctv.channel);
    ctv.displayCaption("Hello, World");
    ctv.caption= true;// 캡션기능을켠다.
    ctv.displayCaption("Hello, World");// 캡션을화면에보여준다.
    }
    }
    1.1 상속의 정의와 장점

    실행결과

    11

    Hello, World

    설명

    자손클래스의 인스턴스를 생성하면 조상클래스의 인스턴스도 같이 생성된다.

    따라서 조상클래스의 인스턴스를 따로 생성하지 않고도 조상 클래스의 멤버들을 사용할 수 있다.
    1.2 클래스간의 관계 – 포함관계

    맨 처음 나타난 클래스간의 관계 : 상속(Inheritance)

    또다른것이있다: 포함(Composite)

    클래스간의 포함관계를 맺어 주는 것은 한 클래스의 멤버변수로 다른 클 래스의 인스턴스를 생성하는 것을 말한다.

    원을 표현하기 위한 Circle 클래스이다.
    class Circle{
    int x;//원점의x좌표
    int y;//원점의y좌표
    int r;//원의반지름
    }

    좌표상의 한 점을 다루기 위해 Point 클래스가 다음과 같이 작성되었다 고 가정하자.
    class Point{
    int x;//원점의x좌표
    int y;//원점의y좌표
    }
    1.2 클래스간의 관계 – 포함관계

    Point 클래스를 재사용해서 Circle 클래스를 작성한다 면다음과같이할수있을것이다.
    class Circle{
    Point p = new Point();//원점
    int r;//원의반지름
    }

    이와 같이 한 클래스를 작성하는데 다른 클래스를 멤버 변수로 정의하여 포함시키는 것을 말 그대로 포함 (Composite)라 한다.

    이렇게 하면 클래스를 작성하는 것이 한결 쉬워진다.
    1.3 클래스간의 관계 결정하기

    클래스 작성시 상속관계인지 포함관계인지를 구분할 때 를 혼동하는 경우가 있다.

    이전의 Circle 클래스의 경우 Point 클래스를 포함하는 대신 상속관계를 맺어주었다면 다음과 같을 것이다.
    class Circle extends Point{
    int r;
    }

    이렇게 본다면 Circle 클래스를 작성하는데 있어 Point 클래스를 포함시키거나 상속받도록 하는 것은 별반 차 이가 없어 보인다.
    1.3 클래스간의 관계 결정하기

    다음과 같이 문장을 만들어 보자.

    Circle은 Point이다 – Circle is a Point.

    Circle은 Point를 가지고 있다 – Circle has a point.

    원은 원점과 반지름으로 구성되므로 위의 두 문장을 비 교해 보면 첫 번째 문장보다 두 번째 문장이 옳다는 것 을 알 수 있을 것이다.

    이처럼 클래스를 가지고 문장을 만들었을 때 ~은이다 라는 문장이 성립한다면 서로 상속관계를 맺어주고

    ~은~을가지고있다는 문장이 성립하면 포함관계를 맺 어주면 된다.

    그래서 Circle과 Point 클래스간의 관계는 포함관계가 적 절하다.
    1.3 클래스간의 관계 결정하기

    정리하자면,

    상속관계 : ~은 ~이다

    포함관계: ~은~를가지고있다.
    1.3 클래스간의 관계 결정하기

    예제 – Point class
    class Point {
    int x;
    int y;
    Point(intx, int y) {
    this.x= x;
    this.y= y;
    }
    Point() {
    this(0,0);
    }
    }
    1.3 클래스간의 관계 결정하기

    예제 – Circle class
    class Circle {
    Point center; // 원의원점좌표
    int r; // 반지름
    Circle() {
    this(newPoint(0, 0), 100);
    }
    Circle(Pointcenter, int r) {
    this.center= center;
    this.r= r;
    }
    }
    1.3 클래스간의 관계 결정하기

    예제 – Triangle class
    class Triangle {
    Point[] p = new Point[3];
    Triangle(Point[] p) {
    this.p= p;
    }
    Triangle(Pointp1, Point p2, Point p3) {
    p[0] = p1;
    p[1] = p2;
    p[2] = p3;
    }
    }
    1.3 클래스간의 관계 결정하기

    예제 – DrawShape class(실행클래스)
    import java.awt.Frame;
    import java.awt.Graphics;
    class DrawShapeextends Frame {
    public static void main(String[] args) {
    DrawShapewin = new DrawShape("도형그리기");
    }
    public void paint(Graphicsg) {
    Point[] p = { new Point(100, 100), new Point(140, 50), new Point(200, 100)};
    Triangle t = new Triangle(p);
    Circle c = new Circle(newPoint(150, 150), 50);
    // 원을그린다.
    g.drawOval(c.center.x, c.center.y, c.r, c.r);
    // 직선3개로삼각형을그린다.
    g.drawLine(t.p[0].x, t.p[0].y, t.p[1].x, t.p[1].y);
    g.drawLine(t.p[1].x, t.p[1].y, t.p[2].x, t.p[2].y);
    g.drawLine(t.p[2].x, t.p[2].y, t.p[0].x, t.p[0].y);
    }
    DrawShape(Stringtitle) {
    super(title);
    setSize(300, 300);
    setVisible(true);
    }
    }
    1.4 단일상속

    C++에서는 여러 클래스로 부터 상속받는 다중상속을 허용하지 만 자바에서는 단일 상속만을 허용한다.

    예를 들어 TV클래스와 VCR클래스가 있을 때, 이 두 클래스로 부터 상속을 받는 TVCR클래스를 작성할 수 없다.

    그래서 TVCR클래스는 조상클래스로 둘 중 하나를 선택해야 한다.

    다중상속은 여러 클래스의 속성을 가져올 수 있다는 장점이 있지만 클래 스간의 관계가 매우 복잡해질 가능성이 있다.

    그 예로 서로 다른 클래스로 부터 상속받은 멤버의 이름이 같은 경우가 생긴다면 이를 구별할 수가 없는 문제가 생긴다.

    따라서 자바에서는 이러한 문제를 원천적으로 제거하기 위해 다중상속 대신 단일 상속만을 채택하였다.

    하나의 조상만을 가진다는 게 불편할 수도 있지만 클래스간의 관계가 보 다 명확해지고 코드를 더욱 신뢰할 수 있게 만들어 준다는 점에서 다중 상속보다 유리하다!
    1.4 단일상속

    예제 – Tv와 VCR class
    class Tv {
    boolean power; // 전원상태(on/off)
    int channel; // 채널
    void power() { power = !power; }
    void channelUp() { ++channel; }
    void channelDown() { --channel; }
    }
    class VCR {
    boolean power; // 전원상태(on/off)
    int counter = 0;
    void power() { power = !power; }
    void play() { /* 내용생략*/ }
    void stop() { /* 내용생략*/ }
    void rew() { /* 내용생략*/ }
    void ff() { /* 내용생략*/ }
    }
    1.4 단일상속

    예제 – TVCR class
    class TVCR extends Tv {
    VCR vcr= new VCR();
    int counter = vcr.counter;
    void play() {
    vcr.play();
    }
    void stop() {
    vcr.stop();
    }
    void rew() {
    vcr.rew();
    }
    void ff() {
    vcr.ff();
    }
    }
    1.4 단일상속

    해설

    다중상속이 허용이 안되므로 Tv클래스를 상속받고 VCR클래 스는 TVCR클래스에 포함 시켰다.

    그리고 TVCR에 VCR클래스의 메서드와 일치하는 이름의 메 서드를 선언하여 내용은 VCR클래스의 것을 호출해서 사용하 도록 하였다.

    이렇게 함으로써 VCR클래스의 내용이 변경되더라도 TVCR 클래스의 메서드들이 변경된 내용이 적용되는 결과를 얻을 수있을것이다.
    1.5 Object클래스

    모든 클래스의 조상

    클래스 상속계층도의 제일 위에 위치하는 조상클래스

    다른 클래스로부터 명시적으로 상속받지 않는 클래스는 자동적 으로 이 클래스를 상속받게 된다.

    예를 들어
    class TV{

    }

    위의 코드를 컴파일 하면 다음과 같이 자동적으로 extends Object를 추가하여 TV클래스가 Object를 상속받게 한다.
    class TV extends Object{

    }
    1.5 Object클래스

    예를 들어 CaptionTV클래스가 상속을 받는다고 가정 할때,
    class CaptionTV extends TV{

    }

    TV클래스가 있고 TV클래스를 상속받는 CaptionTV클래스가 있을 때 상속계층도는 다음과 같다.
    Object
    TV
    CaptionTV
    1.5 Object클래스

    이처럼 모든 상속계층도의 최상위에는 Object클래스가 존재한다.

    그래서 자바의 모든 클래스들은 Object클래스의 멤버 를 상속받는다.

    따라서Object클래스에정의된멤버들을사용할수있 다.

    그런이유로그동안toString()이나equals(Object o)와같은메서드를따로정의하지않고도사용할수 있었던 것이다.
    2.오버라이딩
    2.1 오버라이딩이란?

    조상클래스에서 상속받은 메서드를 자식클래스에서 다 시 만드는 것을 의미한다.

    보통은 그냥 상속받아 사용을 한다.

    하지만 자식클래스의 상황에 맞게 변경해야 하는 경우 이를 오버라이딩한다라고 한다.

    이를 간단하게 아버지의메서드무시하기라고 표현하기도 한 다!
    2.1 오버라이딩이란?

    예제
    class Point{
    int x;
    int y;
    String getLocation(){
    return "x : " + x + ", y : " + y;
    }
    }
    class Point3D extends Point{
    int z;
    String getLocation(){
    return "x : " + x + ", y : " + y + ", z : " + z;
    }
    }
    2.1 오버라이딩이란?

    설명

    Point3D클래스의 입장에서는 좌표 x와 y만을 표시하는 getLocation메서드는 불충분하다.

    따라서 getLocation메서드를 자신의 상황에 맞게, 즉 z를 추가하여 변경을 하게 된 것이다.

    그런데 왜 다른 이름을 사용하지 않았을까?

    이는 새로이 작성된 Point3D클래스가 Point클래스의 후손이므로 Point3D클래스의 인스턴스에 대해서 getLcation메서드를 호출하 면 Point클래스의 getLocation이 그랬듯이 점의 좌표를 문자열로 얻을수있을것이라고기대할것이다.

    그렇기 때문에 새로운 메서드를 제공하는 것 보다는 오버라이딩을 하는 것이 바른 선택이다.
    2.2 오버라이딩의 조건

    오버라이딩의 성립을 위해서는 다음의 조건을 충족해야 한다.

    자손클래스에서 오버라이딩 할려는 메서드는

    조상클래스의 메서드와 이름이 같아야 한다.

    조상클래스의 메서드와 매개변수가 같아야 한다.

    조상클래스의 메서드와 리턴타입이 같아야 한다.

    즉, 같은 메서드여야 한다는 것이다.

    다만 다음의 항목들은 변경이 가능하다

    접근제어자는 변경할 수 있다.

    다만 조상클래스의 원래 메소드보다 더 넓은 범위로 변경해야 한다.

    조상클래스의 메서드보다 많고 넓은 예외를 선언할 수 없다

    주의할 점은 인스턴스 메서드를 오버라이딩을 통해서 static으 로 또는 그 반대로 변경할 수 없다.
    2.3 오버라이딩 VS. 오버로딩

    오버로딩과 오버라이딩의 차이는 명백하다.

    오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것

    오버라이딩 : 상속받은 메서드의 내용을 변경하는 것
    구분
    오버로딩
    오버라이딩
    범위
    한 클래스 내
    상속관계
    개수
    이론상 무한정
    조상클래스와 자식클래스 각 하나씩
    2.4 super

    자식클래스에서 조상클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수

    자기 자신의 참조변수가 this인 반면, 조상클래스의 참조변수를 super라고 이해하면 된다.
    2.4 super

    예제
    class SuperTest {
    public static void main(Stringargs[]) {
    Child c = new Child();
    c.method();
    }
    }
    class Parent {
    int x=10;
    }
    class Child extends Parent {
    void method() {
    System.out.println("x=" + x);
    System.out.println("this.x=" + this.x);
    System.out.println("super.x="+ super.x);
    }
    }
    2.4 super

    실행결과

    x=10

    this.x=10

    super.x=10

    설명

    x라는 변수 즉 상위 클래스의 멤버에 대해서 어떻게 접근해도 같 은 변수임을 보여주고 있다.
    2.4 super

    예제
    class SuperTest2 {
    public static void main(Stringargs[]) {
    Child c = new Child();
    c.method();
    }
    }
    class Parent {
    int x=10;
    }
    class Child extends Parent {
    int x = 20;
    void method() {
    System.out.println("x=" + x);
    System.out.println("this.x=" + this.x);
    System.out.println("super.x="+ super.x);
    }
    }
    2.4 super

    실행결과

    x=20

    this.x=20

    super.x=10

    설명

    이전 예제에서는 멤버변수 x가 상위클래스에서만 선언되었다.

    반면 이 예제는 Child에서도 x가 선언되어 있다.

    따라서 x와 this.x는 Child클래스의 x를,

    super.x는 상위클래스의 x를 가리킨다.

    이처럼 상위클래스에 선언된 멤버변수와 같은 이름의 멤버변수를 하위클래스에서 중복해서 정의하는 것이 가능하다.

    이럴때 x, this.x에서와 보는 바와 같이 기본적(?) 접근이 가능하 며 상위클래스의 멤버에 접근하려면 super를 사용한다.
    2.5 super()- 조상클래스의 생성자

    this()와 마찬가지로 super()역시 생성자이다.

    this()는 같은 클래스내의 다른 생성자를 호출한다.

    super()는 상위클래스의 생성자를 호출한다.

    하위클래스의 인스턴스를 생성할 때,

    하위클래스의 멤버와 상위클래스의 멤버가 같이 초기화 된다.

    그래서 멤버의 초기화하려면 생성자를 호출해야 하므로 상위클래스의 생 성자도 호출된다.

    하위클래스의 생성자에서 맨 처음 수행하는 것이 상위클래스의 생성자 호출이다.

    이는 하위클래스에서 상위클래스의 멤버를 사용할 수도 있기 때문에 상 위클래스의 생성자 호출이 필수적이다.

    상위클래스의 생성자가 매개변수가 없는 생성자이면 생성자 호출을 명시 적으로 하지 않아도 호출이 된다.

    반면에 상위클래스에 매개변수 있는 생성자만 있다면 반드시 명시적으로 호출해줘야 한다.
    2.5 super()- 조상클래스의 생성자

    예제
    class Point {
    int x;
    int y;
    Point(intx, int y) {
    this.x= x;
    this.y= y;
    }
    }
    class Point3D extends Point {
    int z;
    Point3D(int x, int y, int z) {
    this.x= x;
    this.y= y;
    this.z= z;
    }
    }
    class PointTest {
    public static void main(Stringargs[]) {
    Point3D p3 = new Point3D(1,2,3); // 컴파일에러!!!
    }
    }
    2.5 super()- 조상클래스의 생성자

    설명

    이 예제는 컴파일 에러가 발생한다.

    그 이유는 상위클래스인 Point클래스의 생성자는 매개변 수가 있는 생성자인 Point(int x, int y)뿐이다.

    따라서 하위클래스인 Point3D클래스의 생성자는 명시적 으로 상위클래스의 생성자를 호출해 주어야 한다.

    이를 컴파일에러를 없앨려면

    Point3D의 생성자 맨 첫 줄에 super(x, y)와 같이 super를 이용해서 상위클래스의 생성자를 호출해 주어야 한다.

    아니면 Point클래스에 매개변수 없는 생성자 즉, default생성자를 추가해 주어야 한다.
    2.5 super()- 조상클래스의 생성자

    설명

    첫번째 해법
    class Point3D extends Point {
    int z;
    Point3D(int x, int y, int z) {
    super(x, y);
    this.x= x;
    this.y= y;
    this.z= z;
    }
    }
    2.5 super()- 조상클래스의 생성자

    설명

    두번째 해법
    class Point {
    int x;
    int y;
    Point(){}
    Point(intx, int y) {
    this.x= x;
    this.y= y;
    }
    }
    3.package와 import
    3.1 package

    클래스의 묶음을 패키지라고 한다.

    패키지에는 클래스와 인터페이스를 포함 시킬 수 있다.

    서로 연관된 클래스를 그룹단위로 묶어 놓음으로써 효율 적 클래스 관리가 가능하다.
    3.1 package

    클래스가 하나의 물리적 파일이라면,

    패키지는 하나의 물리적 디렉토리이다.

    그래서 특정패키지에 속한 클래스는 실제 그 디렉토리에 존재하는 클래스파일이다.

    디렉토리가 하위 디렉토리를 가질 수 있는 것 처럼 패키 지도 하위 패키지를 가질 수 있다.

    이는 점(.)으로 구분한다.

    예를 들어 java.lang 패키지에서 lang 패키지는 java패키지의 하위 패키지이다.
    3.1 package

    정리하자면,

    하나의 소스파일에는 첫번째 문장으로 단 한번의 패키지 선언을 한다.

    모든 클래스는 반드시 하나의 패키지에 속해야 한다.

    패키지는 점을 구분자로 하여 계층구조로 구성된다

    패키지는 물리적으로 클래스파일을 포함하는 하나의 디렉 토리이다.
    3.2 패키지(package)의 선언

    아주 간단하다

    package 패키지명;
    이렇게 적어주면 된다.

    이와 같은 패키지 선언문은 소스파일에서 주석과 공 백을 제외하고는 맨 처음에 선언되어야 한다.

    패키지명은 대소문자를 구별하지는 않는다.

    하지만 클래스명과의 구별을 위해서 소문자로 하는 것이 원칙이다.

    모든 클래스는 원래 하나의 패키지에 속해있다.

    그러나 이제까지 실습한 파일은 모두 패키지가 선언되지 않았다.

    이는 자바에서 기본적으로 제공하는 이름없는 패키지때문 이다.
    3.2 패키지(package)의 선언

    다음의 예제를 보자
    package com.javachobo.book;
    class PackageTest{
    public static void main(String[] args) {
    System.out.println("HelloWorld!");
    }
    }

    이를 패키지를 적용하여 컴피일을 하려면 다음과 같 이 하여야 한다.

    javac –d PackageTest.java

    그러면 com > javachobo > book 디렉토리에 해당 클래스가 생성되어 있을 것이다.
    3.3 import문

    코드를 작성할 때 다른 패키지의 클래스를 사용하려 면 패키지명이 포함된 클래스 이름을 사용해야 한다.

    하지만 매번 이렇게 패키지명을 붙여서 사용하는 것 이 여간 불편한 것이 아니다.

    코드 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해 주면 소스코드에 사 용되는 클래스이름에서 패키지 명은 생략할 수 있다.
    3.4 import문의 선언

    import문은 package선언문 다음에 그리고 클래스 선언문 이전에 위치해야 한다.

    그리고import문은package문과는달리한소스파 일에 여러 번 선언할 수 있다.

    일반적인 소스파일의 구성은 다음과 같이 되어있다.

    pacakge문

    import문들

    클래스선언

    import문을 선언하는 방법은 다음과 같다.

    import package명.클래스명;
    또는

    import package명.*;
    3.4 import문의 선언

    클래스 이름을 직접 지명하는 대신 *를 사용하면 컴 파일러는 해당 패키지내의 모든 클래스를 import한 다.

    import java.util.Calendar;

    import java.util.Date;

    import java.util.ArrayList;

    이처럼 여러 번 사용하는 대신 이렇게 사용이 가능 하다.

    import java.util.*;

    이렇게 하면 성능저하의 우려가 있다고 주장하는 이들도 있으나 그 차이는 미미하다.
    3.4 import문의 선언

    한가지더염두해두어야할것은*는해당패키지 의 클래스만을 의미한다.

    특정 패키지 하에 클래스와 하위패키지가 있는 경우 패키지는 해당되지 않음에 유의해야 할 것이다.

    import java.util.*;

    import java.text.*;
    이를 다음과 같이 할 수 없다는 뜻이다.

    import java.*;
    3.4 import문의 선언

    예제
    import java.text.SimpleDateFormat;
    import java.util.Date;
    class ImportTest{
    public static void main(String[] args){
    Date today = new Date();
    SimpleDateFormatdate = new SimpleDateFormat("yyyy/MM/dd");
    SimpleDateFormattime = new SimpleDateFormat("hh:mm:ss a");
    System.out.println("오늘날짜는" + date.format(today));
    System.out.println("현재시간은" + time.format(today));
    }
    }
    3.4 import문의 선언

    실행결과

    오늘 날짜는 2009/09/16

    현재 시간은 12:10:58 오후
    3.4 import문의 선언

    설명

    현재 날짜와 시간을 출력하는 예제이다.

    SimpleDateFormat과 Date클래스는 서로 다른 패키지에 포함된 클래스이므로 import문으로 어느 패키지에 속하는 클래스인지 명시했다.

    그래서 소스에서 패키지 명을 생략할 수가 있었다.

    만일 import문을 사용하지 않았다면 다음과 같이 해야 할 것이다.

    java.util.Date today = new java.util.Date();

    java.text.SimpleDateFormat date = new java.text.SimpleDateFormat();

    java.text.SimpleDateFormat time = new java.text.SimpleDateFormat();
    3.4 import문의 선언

    지금까지 System.out.println의 System클래스와 String클래스를 import없이 사용한 이유는

    해당 클래스가 자동적으로 import되는 java.lang 패키지에 포 함되어 있기 때문이다.

    이 패키지는 자주 쓰이는 중요한 클래스들을 모아놓았고 프로 그래밍상의 편의를 위하여 자동적으로 import를 하도록 한 것 이다.
    4.제어자(modifier)
    4.1 제어자(modifier)란?

    제어자라는 것은 클래스, 변수, 메서드의 선언부에 함께 사용되어 그 사용에 있어 부가적인 의미를 더한다.

    제어자의 종류에는

    접근제어자 : public, protected, (default), private

    그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp등

    제어자는 클래스나 멤버변수, 메서드에 주로 사용된다.

    하나의 제어자에 여러 개가 선택되어 사용이 가능하다.

    그러나 접근제어자의 경우 네 가지 중 하나만 선택이 가 능하다.
    4.2 static : 클래스의, 공통적인

    static은 정적인 이라는 의미를 가진다.

    클래스변수 메서드를 만드는데 사용되는데 이 둘은 한번 생성 되면 인스턴스가 몇 개가 만들어 지던지 오로지 하나만 존재하 여 모든 인스턴스가 공유한다.

    사용될 수 있는 곳 : 멤버변수, 메서드, 초기화블록

    멤버변수

    모든 인스턴스에 공통적으로 사용되는 클래스변수

    이는 인스턴스 생성유무에 상관없이 사용 가능

    클래스정보가 메모리에 로드될 때 같이 로드된다.

    메서드

    인스턴스를 생성하지 않고도 호출이 가능한 메서드가 된다.

    이 메서드 내에서는 인스턴스멤버를 직접 사용할 수 없다.
    4.3 final : 마지막의, 변경될 수 없는

    클래스

    변경될 수 없는 클래스 즉 확장이 불가능한 다른 표현으로는 하위클래스를 가질수 없는 클래스가 된다.

    메서드

    변경될 수 없는 메서드.

    즉 오버라이딩이 안된다.

    변수

    상수, 즉 값을 변경할 수 없는 변수가 된다
    4.4 abstract : 추상의, 미완성의

    메서드와 클래스에 사용된다.

    클래스

    클래스내에 추상메서드가 선언되어 있다는 것을 의미한다.

    또는 추상메서드가 없더라도 해당 클래스를 반드시 상속받아 사용하게끔 하고자 한다면 abstract로 선언하는 경우가 있다.

    메서드

    선언부만 작성하고 구현부는 작성하지 않는 메서드이다.

    이를 추상메서드라고 한다.
    4.5 접근제어자 – access modifier

    멤버변수, 메서드, 클래스에 사용되어 접근을 제한하는 역할을 한다.

    접근제어자의 종류 : 4개의 속성과 3개의 키워드로 구성

    private : 같은 클래스내에서만 접근이 가능

    (default) : 같은 패키지내에서만 접근이 가능

    protected : 같은 패키지와 자식클래스에서 접근이 가능

    public : 모든 패키지에서 접근이 가능

    이를 도식화 해 보겠다.
    제어자
    클래스
    패키지
    하위클래스
    전체
    public
    protected
    (default)
    private
    4.6 캡슐화 – 접근제어를 이용한

    캡슐화(encapsulation)이란 private속성을 이용하여 클 래스 외부로부터 특정 데이터에 임의로 접근 하는 것을 차단하고,

    해당 데이터에 접근하기 위한 방법(메서드)을 public으 로 제공하는 기법을 말한다.
    4.6 캡슐화 – 접근제어를 이용한

    다음의 예제를 보자
    class Time{
    public int hour;
    public int minute;
    public int second;
    }

    클래스의 외부에서 이 클래스의 인스턴스를 생성 후 다 음과 같이 하였다고 가정한다면,

    Time t = new Time();

    t.hour = 25;

    이 경우 hour 데이터는 0~24까지의 값만을 가져야 하는데 외 부에서 직접 접근을 하면 이렇게 잘못된 값이 저장 될 위험이 내포되어 있다.
    4.6 캡슐화 – 접근제어를 이용한

    이 경우 다음과 같이 처리하면 된다.
    class Time{
    private int hour;
    private int minute;
    private int second;
    public int getHour() {
    return hour;
    }
    public void setHour(inthour) {
    this.hour= hour;
    }
    public int getMinute() {
    return minute;
    }
    public void setMinute(intminute) {
    this.minute= minute;
    }
    public int getSecond() {
    return second;
    }
    public void setSecond(intsecond) {
    this.second= second;
    }
    }
    4.6 캡슐화 – 접근제어를 이용한

    위의 예제에서 보는 바와 같이

    보호하고자 하는 데이터는 private로

    이에 접근(값을 읽고, 저장하는)할 수 있는 방법을 public 메 서드로 제공하면 된다.

    또한 t.hour = 25;같은 오류를 방지하기 위해서는 값을 저 장하는 부분에 이와 같은 제약조건을 걸면 될 것이다.
    public void setHour(inthour){
    if(hour< 0 || hour > 24) return;
    else this.hour= hour;
    }

    이렇게 하면 hour에 잘못된 값이 저장되는 것을 막을 수 있 다.
    4.7 제어자(modifier)의 조합

    제어자가 사용할 수 있는 대상을 중심으로 정리

    제어자를 조합해서 사용할 때의 주의사항이다.

    메서드에 static과 abstract를 같이 사용할 수 없다.

    클래스에 abstract와 final을 동시에 사용할 수 없다.

    abstract메서드의 접근제어가 private일 수는 없다.

    메서드에 private와 final중 하나만 사용하면 된다.
    대상
    사용가능한 제어자
    클래스
    Public, (default), final, abstract
    메서드
    모든 접근제어자 final, abstract, static
    멤버변수
    모든 접근제어자 final, static
    지역변수
    final
    5.다형성(Polymorphism)
    인터페이스
    (Interface)

    다형성이란

    프로그래밍 언어의 목표

    언어의 목표는 다형성(Polymorphism)에 있다.

    다형성(Polymorphism)의 정의

    하나로 여러 가지 일을 하는 것
    오버라이딩
    (Overriding)
    추상 클래스
    (Abstract Class)
    추상 메서드
    (Abstract Method)
    다운캐스팅
    (Downcasting)
    업캐스팅
    (Upcasting)
    상속과 관련된
    다형성의 기법들
    5.1 배경

    추상클래스의 개념

    추상이라는 단어를 사용하는 객체지향의 기법

    추상 메서드(Abstract Method)

    추상 클래스(Abstract Class)

    public abstract void sayHowareyou();

    메서드의 몸체({})가 없는 메서드를 추상 메서드라고 한다.

    몸체 없는 메서드의 선언부에 abstract키워드를 사용해야 한다.
    5.2 Abstract

    추상클래스의 개념

    public abstract class Test{...}

    몸체 없는 메서드를 포함한 클래스를 추상 클래스라고 한다.

    추상 클래스일 경우 클래스의 선언부에 abstract 키워드를 사 용해야 한다.

    추상 클래스의 예

    public abstract class Test{ //추상클래스를포함클래스

    public void sayHello(){ } //일반 메서드

    public void sayHi(){ } //일반 메서드

    public abstract void sayHello(); //몸체 없는 메서드

    }
    5.2 Abstract

    추상클래스와 추상메서드

    추상 클래스-2개의 추상 메서드를 포함한 추상 클래스의 예
    public abstract class EmptyCan {
    public abstract void printContent(); //추상 메서드
    public abstract void printName(); //추상 메서드
    }

    추상 클래스의 구현-EmptyCan을 상속받아 완전한 클래스 만들기
    public class BeerCan extends EmptyCan{
    public void printContent() {
    System.out.println("흑맥주");
    }
    public void printName() {
    System.out.println("맥주캔입니다.");
    }
    public void sayHello() {
    System.out.println("안녕하세요 맥주캔입니다.");
    }
    public static void main(String args[]) {
    BeerCan b = new BeerCan();
    b.printContent();
    b.printName();
    b.sayHello();
    }
    }
    추상 클래스의 구현
    5.2 Abstract

    추상 메서드를 모두 구현하지 않은 예

    추상 클래스-2개의 추상 메서드를 포함한 추상 클래스의 예
    public abstract class EmptyCan {
    public abstract void printContent();
    public abstract void printName();
    }

    추상의 추상-추상 클래스의 메서드를 모두 구현하지 않은 예
    public abstract class InCompleteCan extends EmptyCan{
    public void printName() {
    System.out.println("InCompleteCan에서printName() 구현");
    }
    }

    모든 추상 메서드의 구현 InCompleteCan에 남아 있던 모든 추상메서드를 구현한 후 객체를 생성하는 예
    public class CompleteCan extends InCompleteCan{
    public void printContent(){
    System.out.println("CompleteCan에서printContent() 구현");
    }
    public void sayHello(){
    System.out.println("CompleteCan에서sayHello() 추가구현");
    }
    public static void main(String args[]) {
    CompleteCancc = new CompleteCan(); //객체생성
    cc.printName();
    cc.printContent();
    cc.sayHello();
    }
    }
    5.2 Abstract
    Circle
    Triangle
    Rectangle
    draw(){..}
    delete(){..}
    Shape
    draw()
    delete()
    draw(){..}
    delete(){..}
    draw(){..}
    delete(){..}
    추상 클래스
    추상 클래스의 구현
    추상 클래스의 구조

    클래스의 구조를 위한 추상클래스
    5.2 Abstract
    5.2 Abstract

    클래스의 구조를 위한 추상클래스

    예제
    abstract class Shape {
    public abstract void draw();
    public abstract void delete();
    }
    class Circle extends Shape {
    public void draw() {
    System.out.println("원을그립니다");
    }
    public voiddelete() {
    System.out.println("원을지웁니다");
    }
    }
    class Triangle extends Shape {
    public void draw() {
    System.out.println("삼각형을하나, 둘, 셋, 그립니다.");
    }
    public void delete() {
    System.out.println("삼각형을지웁니다");
    }
    }
    class Rectangle extends Shape {
    public void draw() {
    System.out.println("사각형을원, 투, 쓰리, 포그립니다.");
    }
    public void delete() {
    System.out.println("사각형을지웁니다");
    }
    }
    5.2 Abstract

    클래스의 구조를 위한 추상클래스

    예제
    public class ShapeMain {
    public static void main(String[] args) {
    Circle c = new Circle();
    Triangle t = new Triangle();
    Rectangle r = new Rectangle();
    //1. 각각의도형그리기
    c.draw();
    t.draw();
    r.draw();
    //2. 각각의도형지우기
    c.delete();
    t.delete();
    r.delete();
    }
    }
    5.2 Abstract

    추상 메서드를 포함하지 않은 추상 클래스

    추상 메서드를 포함하지 않으면서 추상 클래스로만 명시된 경우
    public abstract class SimpleAdapter{
    public void printHello(){
    System.out.println("SimpleAdapter의printHello()");
    }
    }

    상속만으로 구현되는 추상 클래스
    class SimpleCollector extends SimpleAdapter{
    //...내용없음
    }
    public class SimpleMain{
    public static void main(String[] args){
    SimpleCollector s = new SimpleCollector();//객체생성
    s.printHello(); //멤버메서드호출
    }
    }
    상속만으로 완전한 클래스가 된다.
    5.3 인터페이스

    인터페이스란?

    인터페이스(Interface)의 정의

    골격만 가지고 있는 클래스

    몸체 없는 메서드(추상 메서드)로만 이루어진 클래스

    인터페이스도 클래스의 한 종류다.

    추상 클래스 VS. 인터페이스

    추상 클래스는 클래스의 일부분이 추상 메서드이다.

    인터페이스는 추상 메서드로만 이루어져 있다.

    추상 클래스는 extends를 이용해서 추상 메서드를 구현 한다.

    인터페이스는 implements를 이용해서 추상 메서드를 구 현한다.
    5.3 인터페이스

    일반적인 인터페이스의 구조

    IRemoteControl 인터페이스
    public interface IRemoteControl{
    void powerOn(); //추상메서드
    void powerOff(); //추상메서드
    void channelUp(); //추상메서드
    void channelDown(); //추상메서드
    }

    인터페이스를 전부 구현하지 않아서 다시 추상 클래스가 되는 예제
    public abstract class RemoteTV implements IRemoteControl{
    protected int nChannel = 0;
    protected boolean bPower = false;
    public void powerOn(){//추상메서드재정의
    bPower = true;
    System.out.println("TV전원On!");
    }
    public void powerOff(){//추상메서드재정의
    bPower = false;
    System.out.println("TV전원Off!");
    }
    public void channelUp() {//추상메서드재정의
    nChannel++;
    System.out.println("TVChannel Up " + nChannel);
    }
    }
    5.3 인터페이스

    일반적인 인터페이스의 구조

    추상클래스를 구현하는 예
    public class LGRemoteTVextends RemoteTV{
    public void channelDown() {
    nChannel--; //nChannel은protected로선언
    System.out.println("TVChannel Down "
    + nChannel);
    }
    public static void main(String[] args){
    LGRemoteTVtv= new LGRemoteTV();
    tv.powerOn();
    tv.channelUp();
    tv.channelDown();
    tv.powerOff();
    }
    }
    5.3 인터페이스

    인터페이스에서 사용할 수 있는 멤버변수

    BodySign인터페이스를 구현하는 예제
    public interface BodySign{
    //1. 키워드를명시하지않은경우
    int CENTER = 1;
    int LEFT = 2;
    int RIGHT = 3;
    int DOWN = 4;
    int UP = 5;
    void throwBall(inthow);
    }
    5.3 인터페이스

    인터페이스에서 사용할 수 있는 멤버변수

    BodySign인터페이스를 구현하는 예제
    public class Pitcher implements BodySign {
    public void throwBall(inthow){
    if(how== BodySign.CENTER){
    System.out.println("Center로던집니다.");
    }else if(how== BodySign.LEFT){
    System.out.println("Left로던집니다.");
    }else if(how== BodySign.RIGHT){
    System.out.println("Right로던집니다.");
    }else if(how== BodySign.DOWN){
    System.out.println("Down으로던집니다.");
    }else if(how== BodySign.UP){
    System.out.println("Up으로던집니다.");
    }else{
    System.out.println("이상한볼입니다.");
    }
    }
    public static void main(String[] args) {
    Pitcher p = new Pitcher();
    p.throwBall(BodySign.CENTER); //final static 변수를사용
    p.throwBall(BodySign.LEFT);
    p.throwBall(BodySign.RIGHT);
    p.throwBall(BodySign.DOWN);
    p.throwBall(BodySign.UP);
    }
    }
    5.3 인터페이스
    다중 상속의 문제점
    아버지F
    아들A
    아버지F
    아들B
    아버지F
    다중상속
    손자C
    아들A
    아버지F
    아들B
    아버지F
    손자C가 아들A와 아들B를 동시에 상속했을 때 손자C 는 같은 아버지F를 두개 보 유한 상태가 된다
    단일상속
    단일상속
    부모가 다르면 상속의 장점은 극대화된다.(interface를 사용하는 이유: 부모가 다르다는 것이 보장되기 때문)
    Say();
    손자C t1 = new 손자C();
    t1.say(); //모호
    아버지F t2 = t1;//모호
    문제점1
    문제점2
    문제점3

    다중상속과 인터페이스
    5.3 인터페이스

    인터페이스를 이용한 다중상속의 예 I

    Queue 형태로 데이터를 삽입하고 추출하는 인터페이스
    public interface IQueue{
    void enQueue(String video);
    String deQueue();
    }

    저장소 역할을 하는 클래스
    import java.util.Vector;
    public class Shop{
    protected Vector store = new Vector();
    public int getCount(){
    return store.size();
    }
    }
    5.3 인터페이스

    인터페이스를 이용한 다중상속의 예 I

    IQueue와 Shop을 동시에 상속하고 구현한 예
    public class VideoShop extends Shop implements IQueue{
    public void enQueue(String video){
    System.out.println(video + "반납");
    this.store.addElement(video);
    }
    public String deQueue(){
    return (String)this.store.remove(0);
    }
    }
    5.3 인터페이스

    인터페이스를 이용한 다중상속의 예 I

    VideoShop 클래스를 테스트하는 예
    public class VideoShopMain{
    public static void main(String[] args){
    String temp;
    VideoShopvs= new VideoShop();
    System.out.println("보유한비디오개수는" + vs.getCount());
    //1. 3개의비디오반납
    vs.enQueue("메트릭스1"); //비디오반납
    vs.enQueue("메트릭스2"); //비디오반납
    vs.enQueue("메트릭스3"); //비디오반납
    System.out.println("보유한비디오개수는" + vs.getCount());
    //2. 3개의비디오빌려줌
    temp = vs.deQueue(); System.out.println(temp+ " 빌림");
    temp = vs.deQueue(); System.out.println(temp+ " 빌림");
    temp = vs.deQueue(); System.out.println(temp+ " 빌림");
    System.out.println("보유한비디오개수는" + vs.getCount());
    }
    }
    5.3 인터페이스

    인터페이스를 이용한 다중상속의 예 II.
    IQueue Interface
    인터페이스
    다중 상속 클래스의 구조
    enQueue()
    deQueue()
    Shop 클래스
    Vector store
    getCount()
    VideoShop 클래스
    Vector store
    getCount()
    클래스
    다중 상속 클래스
    enQueue()
    deQueue()
    IQueue
    Shop
    삭제
    저장공간
    저장된 데이터 개수
    삽입
    5.3 인터페이스

    인터페이스를 이용한 다중상속의 예 II

    public class VideoShop extends Shop implements IQueue, IClientManager, IAccount{...}

    extends로는 하나의 클래스만 사용할 수 있으며, implements는 여러 개의 인터페이스를 사용할 수 있다.

    인터페이스를 구분할 때에는 콤마(,) 연산자를 이용한다.
    5.4 Upcasting

    Upcasting

    업캐스팅(Upcasting)이란?

    특정 객체가 하위 클래스의 형에서 상위의 클래스의 형으로 캐 스팅되는 것

    업캐스팅(Upcasting)의 특징

    형만 정확하다면 묵시적으로 캐스팅된다.
    인터페이스
    (Interface)
    오버라이딩
    (Overriding)
    추상 클래스
    (Abstract Class)
    가상 메서드
    (Virtual Method)
    상속
    (Inheritance)
    업캐스팅과
    연결되는 기술들
    5.4 Upcasting

    기본 데이터 타입의 캐스팅

    캐스팅(Casting)

    기본 데이터 타입의 경우

    큰 데이터 타입의 데이터를 작은 데이터 타입에 할당하는 것은 데이 터의 손실이 발생

    클래스의 경우

    하위 클래스의 객체를 상위 클래스 형의 객체로 캐스팅하는 것이 가 능하다.
    5.4 Upcasting

    기본 데이터 타입의 캐스팅

    byte형을 int형으로 자동 캐스팅

    byte b = 127;

    int i = b;

    int형을 byte형으로 캐스팅하면 컴파일 에러 발생

    int i = 128;

    byte b = i;

    해결책:강제로 캐스팅을 하고자 한다면 캐스팅 연산자 사용

    b = (byte)i; //오버플로우 발생
    에러 발생
    5.4 Upcasting
    class Animal {
    //클래스내부작업
    }
    class Dog extends Animal{
    //클래스내부작업
    }
    public class DogMain{
    public static void main(String[] args){
    Animal ani= new Dog();
    }
    }
    업캐스팅(Upcasting)을 했을 때 접근여부
    Animal
    Dog
    Animal ani
    Animal 형의 메모리
    Animal ani = new Dog()
    ani로 접근할 수 있는 부분
    Animal
    Animal 형의 메모리
    Animal 클래스
    Dog 형의 추가 메모리
    Dog 클래스
    접근할수없는
    메모리 영역

    클래스의 업캐스팅
    5.4 Upcasting
    캐스팅때문에접근할수없는영역
    draw()
    draw()
    Shape
    1
    Shape
    Circle
    s 로호출할수있는 메서드
    Shape s = new Circle()
    s.draw() 호출
    재정의
    되었는지 확인
    ?
    2
    no
    3
    3
    yes
    재정의 되었다면
    Circle의 draw() 호출
    재정의 되지 않았다면
    Shape의 draw() 호출
    업캐스팅으로 인해 접근할 수 없는 영역에 대한 접근
    draw()
    Circle 클래스
    Shape 클래스
    업캐스팅으로 인해 발생하는
    손실된 부분의 메모리에 접근
    하기 위해서 오버라이딩과
    가상 메서드의 기법을 이용한다.

    클래스의 업캐스팅의 예
    5.4 Upcasting

    클래스의 업캐스팅의 예
    class Shape{
    public void draw(){
    System.out.println("도형을그립니다.");
    }
    }
    class Circle extends Shape{
    private String type = "원";
    public void draw(){
    System.out.println(type + "을그립니다.");
    }
    }
    public class UpcastingMain{
    public static void main(String[] args){
    Circle c = new Circle();
    c.draw(); //Circle의draw() 호출
    Shape s = c;//업캐스팅
    s.draw(); //업캐스팅후상위클래스의이름으로draw() 호출
    }
    }
    5.4 Upcasting

    추상 클래스의 업캐스팅
    abstract class Bell {
    public abstract void ring();
    }
    class AlarmBell extends Bell{
    public void ring(){
    System.out.println("삐리리릭! 삐리리릭!");
    }
    }
    public class AbstractMain{
    public static void main(String[] args){
    Bell b = new AlarmBell();
    b.ring();
    }
    }
    extends
    추상 클래스
    추상 클래스의 상속
    추상 메서드
    추상 클래스에 존재하는 추상 메서드에서의 가상 메서드 호출
    5.4 Upcasting

    인터페이스의 업캐스팅
    interface Tree{
    void leafShape();
    }
    class PineTree implements Tree{
    public void leafShape(){
    System.out.println("나뭇잎은뾰족합니다.");
    }
    }
    public class InterfaceMain{
    public static void main(String[] args){
    Tree t = new PineTree();
    t.leafShape();//PineTree의leafShape() 호출
    }
    }
    implements
    인터페이스
    인터페이스에 존재하는 추상 메서드에서의 가상 메서드 호출
    인터페이스의 구현
    추상 메서드
    5.4 Upcasting

    업캐스팅을 이용하는 변신 자동차
    interface IFork {
    void dig();
    }
    interface ITank {
    void shoot();
    }
    abstract class AutoCar {
    public abstractvoid drive();
    }
    class MadCar extends AutoCar implements IFork, ITank{
    public void dig(){
    System.out.println("땅을파고있습니다.");
    }
    public void shoot(){
    System.out.println("포를쏘고있습니다.");
    }
    public void drive(){
    System.out.println("운전을하고있습니다.");
    }
    public void soundHorn(){
    System.out.println("빠아앙! 빠아앙!");
    }
    }
    5.4 Upcasting

    업캐스팅을 이용하는 변신 자동차
    public class MadCarMain{
    public static void main(String[] args){
    MadCarm = new MadCar();
    m.dig();
    m.shoot();
    m.drive();
    m.soundHorn();
    //1. IFork인터페이스로업캐스팅
    IForkf = m;
    f.dig();
    //2. ITank인터페이스로업캐스팅
    ITankt = m;
    t.shoot();
    //3. AutoCar추상클래스로업캐스팅
    AutoCarc = m;
    c.drive();
    }
    }
    5.4 Upcasting
    t 로 호출할 수 있는 메서드
    dig()
    IFork
    shoot()
    drive()
    AutoCar
    dig()
    shoot()
    drive()
    soundHorn()
    MadCar
    1
    ITank t = new MadCar()
    t.soundHorn() 호출
    2
    ITank로는 shoot()만 호출 가능하다.
    재정의되지 않았기
    때문에 호출할 수 없다.
    호출할 수 있는 메서드와 없는 메서드
    shoot()
    ITank
    에러
    ITank
    주의
    하위 클래스의 객체를 상위 클래스의 형으로 업캐스팅했을 때 상위 클래 스의 이름으로 재정의되지 않은 메서드를 호출할 수 있는 방법은 없다.
    즉, 하위 클래스에만 존재하는 메서드는 상위 클래스에서호출할 수 없다.
    MadCar 클래스
    ITank 인터페이스

    MadCar의 호출 가능한 메서드

    dig(), shoot(), drive(), soundHorn()

    ITank의 호출 가능한 메서드

    shoot()

    IFork의 호출 가능한 메서드

    dig()

    AutoCar의 호출 가능한 메서드

    drive()

    호출 불가능한 예

    IFork f = new MadCar();

    f.shoot(); //IFork f로 ITank의 shoot() 호출 - 불가능

    f.drive(); //IFork f로 AutoCar의 drive() 호출 - 불가능

    업캐스팅시주의사항
    5.4 Upcasting
    MadCar클래스dig()IForkshoot()drive()AutoCardig()shoot()drive()soundHorn()MadCarAutoCar클래스호출가능한메서드의목록IFork인터페이스ITank인터페이스ITankdig()IForkdrive()AutoCarshoot()ITankMadCar클래스dig()shoot()drive()soundHorn()MadCar

    업캐스팅시주의사항
    5.4 Upcasting

    인터페이스와 업캐스팅의 진정한 의미

    인터페이스를 사용하는 목적 I

    자바의 interface는 사용자와의 상호작용(인터페이스)을 위해서 사용한다.

    공개된 IFork 인터페이스를 이용한 메서드 호출

    IFork f = new MadCar();

    f.dig();
    5.4 Upcasting

    인터페이스와 업캐스팅의 진정한 의미

    인터페이스를 사용하는 목적 II

    사용자에게 interface만을 공개했을 때 해당 객체가 다양한 기 능을 보유하더라도 interface에 해당하는 기능만을 사용하게 할수있다.

    인터페이스를 사용하는 목적 III

    interface로 작업을 제한했기 때문에 해당 객체를 잘못 사용하 는 오류를 막을 수 있다.

    interface를 사용하면 다중 상속의 장점을 이용할 수 있으며, 사용자에게 모든 작업을 공개하는 것이 아니라 interface를 통 해서 필요한 작업만을 하게함으로써 사용자는 더욱 쉽게 작업 을 할 수 있으며 객체를 잘못 사용하는 오류를 막을 수 있다.
    5.4 Upcasting

    인터페이스의 넓은 의미

    IProcess 인터페이스
    interface IProcess {
    int run();
    }

    IProcess 인터페이스를 구현한 Kim 클래스
    class Kim implements IProcess{
    // ... 내부에run() 구현
    }

    IProcess 인터페이스를 구현한 Park 클래스
    class Park implements IProcess{
    // ... 내부에run() 구현
    }

    Kim, Park 클래스의 메서드
    IProcesskim= new Kim();
    int a = kim.run();
    IProcesspark = new Kim();
    int b = park.run();
    5.5 Downcasting

    다운캐스팅이란

    다운캐스팅(Downcasting)

    업캐스팅(Upcasting)한 것을 다시 원래의 형으로 복원시켜 주 는작업

    다운캐스팅(Downcasting)의 특징

    업캐스팅된 것만 다운캐스팅 시킬 수 있다.

    다운캐스팅은 강제 캐스팅을 원칙으로 한다.
    draw()
    Shape
    Circle
    Shape s = new Circle()
    업캐스팅(Upcasting)과 다운캐스팅(Downcasting)
    draw()
    Circle 클래스
    Circle c = (Circle)s;
    draw()
    Shape
    Circle
    draw()
    Circle 클래스
    업캐스팅 된 것만이 다운캐스팅될 수 있다.
    5.5 Downcasting

    다운캐스팅의 예

    Object 클래스

    모든 클래스는 Object 클래스를 상속받으며, Object 클래스는 모든 클래스의 최 상위 클래스가 된다.

    다운 캐스팅의 테스트
    class DownTop extends Object{
    //클래스내용
    }
    public class DownTopMain{
    public static void main(String[] args) {
    DownTop d = new DownTop();
    Object obj = d;//업캐스팅은묵시적으로이루어진다.
    System.out.println("Objectobj => " + obj);
    DownTop t = (DownTop)obj;//다운캐스팅-강제캐스팅
    System.out.println("DownTopt => " +t);
    }
    }
    class DownTop {
    //클래스내용
    }
    동일한 클래스
    5.5 Downcasting

    다운캐스팅의 형확인

    instanceof의 사용
    Object obj = new DownTop();
    if(obj instanceof DownTop){ //형확인
    //obj가 DownTop형이라면 이 부분이 실행
    }

    형확인 후 다운 캐스팅
    class OkDown extends Object{
    //내용없음
    }
    public class OkDownMain{
    public static void main(String[] args) {
    OkDown d = new OkDown();
    Object obj = d;//업캐스팅은묵시적으로이루어진다.
    System.out.println("Objectobj => " + obj);
    if( obj instanceof OkDown ) {//형확인
    OkDown okt = (OkDown)obj;
    System.out.println("OkDownt => " + okt);
    }else{
    System.out.println("형이맞지않습니다.");
    }
    }
    }
    5.5 Downcasting

    업캐스팅의 장점(자바 1.4까지)

    Vector를 사용할 때의 업캐스팅

    String str = new String("안녕하세요");

    Integer ig = new Integer(1000);

    Vector v = new Vector();

    v.addElement(str); //업캐스팅 발생

    v.addElement(ig); //업캐스팅 발생

    addElement()의 매개변수에서 일어나는 업캐스팅

    v.addElement(str);에서 발생하는 업캐스팅 : Object obj = str;

    v.addElement(ig); : Object obj = ig;
    5.5 Downcasting

    업캐스팅의 장점(자바 1.4까지)

    Vector에는 객체만을 삽입할 수 있다.

    Vector v = new Vector();

    int a = 1000;

    v.addElement(1000); //오류 -기본 데이터 타입

    v.addElement(a); //오류 -기본 데이터 타입의 데이터나 변수는 객체가 아니다.

    래퍼(Wrapper) 클래스 만들기

    1000 -> new Integer(1000)

    3.14f -> new Float(3.14f)

    2000 -> new Long(2000L)
    5.5 Downcasting

    업캐스팅의 장점(자바 1.4까지)

    Vector 클래스

    단순한 저장소 역할을 하는 클래스

    데이터가 삽입된 순서대로 저장된다.

    Object형의 매개변수

    public void addElement(Object obj)

    업캐스팅의 장점

    업캐스팅의 기법을 이용하면 상위 클래스를 상속받은 모든 하 위 클래스의 객체를 수용할 수 있다.

    래퍼(Wrapper) 형식의 클래스

    래퍼(Wrapper) 형식의 클래스란 기본 데이터 타입을 클래스 타입으로 포장하는 클래스를 말한다.

    각각의 기본 데이터 타입에 해당하는 래퍼(Wrapper) 형식의 클래스가 하나씩 존재한다.
    5.5 Downcasting

    업캐스팅의 장점(자바 1.4까지)
    5.5 Downcasting

    String name = new String("홍길동");

    Integer id = new Integer(1000);

    Vector v = new Vector();

    v.addElement(name); //자동 업캐스팅

    v.addElement(id); //자동 업캐스팅
    0: Object
    1: Object
    Vector v = new Vector()
    v.addElement( name );
    v.addElement( id );
    String name = new String("홍길동");
    Integer id = new Integer(1000);
    Object obj = name;
    Object obj = new String("홍길동");
    Object obj = id;
    Object obj = new Integer(1000);
    Object obj1 = v.elementAt( 0 );
    String str2 = (String)obj1;
    addElement(Object obj)
    elementAt(int index)
    String str2 = (String)v.elementAt(0);
    Integer num2 = (Integer)v.elementAt(1);
    Object obj2 = v.elementAt( 1 );
    Integer num2 = (Integer)obj2;
    Vector의 데이터 삽입과 추출

    Object obj1 = v.elementAt(0); //강제 다운캐스팅

    Object obj2 = v.elementAt(1); //강제 다운캐스팅

    String str = (String)obj1;

    Integer num = (Integer)obj2;

    String str2 = (String)v.elementAt(0); //강제 다운캐스팅

    Integer num2 = (Integer)v.elementAt(1); //강제 다운캐스팅

    업/다운캐스팅의 예(자바 1.4까지)
Designed by Tistory.