본문 바로가기

프로그래밍/자바(java)

[자바/java] 클래스(class) 접근제한자, 오버라이딩, 상속

저번에 이어서 클래스 두번째 시간을 가지도록 하겠습니다.

 

저번에 배운 메소드에는 리턴 타입이 이라는게 있는데 리턴값이 있는 메소드, 리턴값 없는 메소드(void)이 있습니다.

 

 

class Scratch {
    public static void main(String[] args) {

        favorite favorite = new favorite();

        System.out.println(favorite.getIdol());

        System.out.println("====================");

        favorite.setIdol("ITZY");
        System.out.println(favorite.getIdol());

    }
}

class favorite {

    String idol = "트와이스";

    public String getIdol() {
        return idol;
    }

    public void setIdol(String singer) {
        this.idol = singer;
    }

}

 

 

밑에 favorite 클래스를 보면 getIdol() , setIdol() 이 있는데 getIdol를 보면 public String 리턴 타입이 있습니다.

그리고 return 이라는게 실행문 안에 있는데 return 뒤에 있는 String 타입 값을 내보내는 것입니다.

꼭 리턴 타입을 맞춰서 return 을 해줘야 합니다.

또 void 는 거의 입력이나 어떤한 프로그램을 돌리기 위해 많이 사용하는데 return 값이 없는 것이 특징입니다.

this

class Scratch {
    public static void main(String[] args) {

        favorite favorite = new favorite();

        favorite.setIdol("ITZY");

    }
}

class favorite {

    String idol = "트와이스";

    public void setIdol(String idol) {
        System.out.println("this.idol = " + this.idol);
        System.out.println("idol = " + idol);
    }

}

 

favorite 클래스의 setidol 클래스를 실행해 보면 위 처럼 실행 결과가 나온다.

원래는 this.idol = idol 로 넣은 값을 넣어주는 역활을 하지만 this.idol과 그냥 idol 변수가 어떤거 인지 알려주기 위해 값을 출력해 보았습니다.

this.idol 은 기존에 넣은거 즉, 클래스 안에 변수안에 있는 값이라고 생각해주시면 된다.

idol 변수는 매개변수이여서 넣을는 값 ITZY 가 표시가 됩니다.

Static

 

처음 java를 공부하려면 이 것을 많이 볼텐데 public 과 void 사이에 static???

필드에도 static을 붙일 수 있고 메소드에도 붙을 수 있다.

메소드 영역 에 저장이 되어 기존에 new 를 사용하여 인스턴스 필드를 선언하여 사용하였지만 static을 사용하면 사용할 수 있다.

class Scratch {
    public static void main(String[] args) {

        System.out.println(favorite.getIdol());

    }
}

class favorite {

    static String idol = "트와이스";

    public static String getIdol() {
        return idol;
    }

}

 

이런식으로 static을 사용하면 쉽게 사용할 수 있다.

하지만, 데이터영역은 JVM이 끝나지 전에는 사라지지 않기 때문에 이 점 기억해 주셨으면 좋겠습니다.

final

final은 필드에 초기값이 저장 되면 이것이 최종값이 되어 수정을 할 수 없다.

 

 

 

이런식으로 from에 final 을 지정한걸 수정 할 수 없다 (오류가 난다)

 

class Math {
    
    static final double PI = 3.14159;
    
}

 

 

위에 static과 final 을 모두 사용한것입닏다. 이걸 상수라고 하는데, 변하지 않는 값이며 다른곳에서도 똑같은것으로 쓰여야하고 같은 이름으로 만들어져서는 안된다. 그렇기 때문에 static과 final 의 특징이 둘다 가져야 상수인 것이다.

접근 제한자

 

 

class 를 제어하는 것으로 4개의 접근 제한을 가질수 있게 한다.

 

이런식으로 제한을 걸 수 있다.

 

이런 식으로 접근 제한에 따라 인스턴스가 생성될 수 있고 없고 할 수 있다.

상속

상속(Inheritance) 은 부모가 자식에게 물려주는 행위입니다. 프로그램에서는 부모클래스의 필드나 메소드를 자식 클래스에게 물려주는 것이다.

class Scratch {

    public static void main(String[] args) {

        child child = new child();

        System.out.println(child.blog_url); // naver.com
        child.GetBlog_count();              // 24
        child.GetBlog();                    // 개발보다 집중

    }

}

class Parent {

    String blog = "개발보다 집중";
    String blog_url = "naver.com";

    void GetBlog() {
        System.out.println(blog);
    }

    void GetBlog_url() {
        System.out.println(blog_url);
    }

}

class child extends Parent {

    int blog_count = 24;

    void GetBlog_count() {
        System.out.println(blog_count);
    }

}
​

 

이런식으로 한 클래스에 필드와 메소드를 주어 한 클래스로 두개의 클래스 역활을 할 수 있게 된다.

상속은 extends 그리고 상속은 여러개 쓸수 없고 상속은 한 개 만 와야 한다.

오버라이딩(Override)

모든 클래스에 중첩 안되게 설계되어 사용하게 되면 좋지만 똑같은 이름의 메소드가 수정이 되어야 할때가 있다.

그렇때는 @override를 사용하여 수정 하여 사용할 수 있다.

 

class Scratch {

    public static void main(String[] args) {

        child child = new child();

        child.GetBlog();                // 오버라이딩으로 변경해봤습니다.

    }

}

class Parent {

    String blog = "개발보다 집중";
    String blog_url = "naver.com";

    void GetBlog() {
        System.out.println(blog);
    }

    void GetBlog_url() {
        System.out.println(blog_url);
    }

}

class child extends Parent {

    int blog_count = 24;

    void GetBlog_count() {
        System.out.println(blog_count);
    }

    @Override
    void GetBlog() {
        System.out.println("오버라이딩으로 변경해봤습니다.");
    }

}
​

 

 

super

부모 클래스에 자식 메소드가 숨겨지고 오라이딩된 자식 메소드만 사용된다. 부모클래스의 메소드를 호출해야 하는 상황이 오면 super을 사용하여 부모 메소드에 접근 할 수 있다.

 

class Scratch {

    public static void main(String[] args) {

        child child = new child();

        child.GetBlog();                // 오버라이딩으로 변경해봤습니다.
                                        // naver.com

    }

}

class Parent {

    String blog = "개발보다 집중";
    String blog_url = "naver.com";

    void GetBlog() {
        System.out.println(blog);
    }

    void GetBlog_url() {
        System.out.println(blog_url);
    }

}

class child extends Parent {

    int blog_count = 24;

    void GetBlog_count() {
        System.out.println(blog_count);
    }

    @Override
    void GetBlog() {
        System.out.println("오버라이딩으로 변경해봤습니다.");
        super.GetBlog_url();
    }

}

 

이런식으로 super을 사용하면 부모 클래스의 메소드도 같이 값이 출력이 된다.

※ 여기서 주의 final로 된 메소드나 필드는 상속 받을 수 없다. 그리고 class 에 final 이 되어있으면 상속 받을 수 없다.

타입 변환

이 처럼 부모 클래스 자식 클래스를 넣는데 순서가 다를 면 강제 타입 변환, 자동 타입 변환 둘로 나눌 수 있고

부모타입에 자식을 넣게 되면 자식에만 있는 것을 쓸 수 가 없다.

강제 타입 변환에는 객체 타입을 앞에 적어 줘야 변환을 할 수 있다.

 

class Scratch {

    public static void main(String[] args) {

        Parent parent = new child();    // 자동 타입변환

        System.out.println(parent.blog);    // 개발에 집중
 //       System.out.println(parent.blog_count); // (x) -- child에만 있는 값

        child child = (child) parent;   // 강제 타입 변환

    }

}

class Parent {

    String blog = "개발보다 집중";
    String blog_url = "naver.com";

    void GetBlog() {
        System.out.println(blog);
    }

    void GetBlog_url() {
        System.out.println(blog_url);
    }

}

class child extends Parent {

    int blog_count = 24;

    void GetBlog_count() {
        System.out.println(blog_count);
    }

    @Override
    void GetBlog() {
        System.out.println("오버라이딩으로 변경해봤습니다.");
        super.GetBlog_url();
    }

}

 

객체 타입 확인(instanceof)

instanceof 는 어떤 객체가 어떤 클래스의 인스턴스 인지 확인하려고 이 연산자를 사용한다.

좌항(객체) instanceof 우항(타입) 형태로 사용할수 있다.

ex) 자식 객체 instanceof 부모형태 이면 true - > 자동 형 변황 경우

부모 객체 instanceof 자식형태 이면 flase -> 강제 형 변환 경우

로 나타낸다.

 

 

class Scratch {

    public static void main(String[] args) {

        Parent parent = new child();    // 자동 타입변환

        System.out.println(parent.blog);    // 개발에 집중
 //       System.out.println(parent.blog_count); // (x) -- child에만 있는 값

        if (parent instanceof child) {  // 변할 수 있는지 parent가 child 객체로 변할 수 있는지 ?  ( true )
            child child = (child) parent;   // 강제 타입 변환
        }


        Parent parent2 = new Parent();
        System.out.println(parent2 instanceof child);       // false 부모 객체는 자식으로 바꾸려면 (강제변환 필요)

    }

}

class Parent {

    String blog = "개발보다 집중";
    String blog_url = "naver.com";

    void GetBlog() {
        System.out.println(blog);
    }

    void GetBlog_url() {
        System.out.println(blog_url);
    }

}

class child extends Parent {

    int blog_count = 24;

    void GetBlog_count() {
        System.out.println(blog_count);
    }

    @Override
    void GetBlog() {
        System.out.println("오버라이딩으로 변경해봤습니다.");
        super.GetBlog_url();
    }

}

 

 

추상 클래스

추상(abstract)은 실체 간에 공통되는 특성을 추출한 것을 말한다.

객체를 직접 생성 할 수 있는 클래스를 실체 클래스라고 하면 이 클래스의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 한다.

추상클래스로 된 클래스는 new 연산자로 인스턴스 생성시키지 못한다.

 

 

class Scratch {

    public static void main(String[] args) {

 //       Phone phone = new Phone();      // (x) 추상 클래스는  선언 불가

        samsung samsung = new samsung();
        apple apple = new apple();

        samsung.home_buttom();
        samsung.AI();

        apple.home_buttom();
        apple.AI();

    }

}

abstract class Phone {

    String company;

    Phone() {}

    void getCompany() {
        System.out.println(company);
    }

    abstract void AI();

    void home_buttom() {
        System.out.println("홈으로");
    }

}

class samsung extends Phone {

    samsung() {
        super();
        this.company = "삼성";
    }

    @Override
    void AI() {
        System.out.println("하이 빅스비");
    }
}

class apple extends Phone {

    apple() {
        super();
        this.company = "애플";
    }

    @Override
    void AI() {
        System.out.println("시리야~");
    }
}

 

이런식으로 쓸 수 가 있다.

추상클래스는 생성자를 호출 할 수 없으므로 상속 받은 클래스에 super()로 phone 객체를 생성하여 사용 할 수 있다.

abstract void AI() 처럼 추상 메소드로 되어 있으면 실행문을 적을 수 없고 상속 받은 곳에서는 무조건 저 메소드를 재정의(오버라이딩)을 해줘야 한다.

이처럼 한 클래스에 samsung 을 넣으면 samsung_phone의 역활을 하고 apple을 넣으면 apple_phone이 되는 점이 다형성이라고 한다.