본문 바로가기
명품 자바

명품자바 5장

by hoshi03 2023. 12. 26.

상속

 

서브 클래스는 슈퍼 클래스의 private 이외의 멤버에 접근 가능

 

animal, person 클래스가 잇을때

super(x, y) 로 person 클래스의 상위 클래스인 animal(x,y)를 호출할 수 있다

 

업캐스팅 - 서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환

업캐스팅은 슈퍼 클래스가 서브 클래스 객체를 가리킨다

Peroson p;
Student s = new Student();
p = s;

위에서 만든 p는 s를 가리키지만 Person 클래스의 멤버만 접근 가능하다

업캐스팅시 명시적으로 타입을 변환 하지 않아도 된다, Student 객체는 Person 타입이기 때문이다

 

다운캐스팅 - 업캐스팅과 반대로 슈퍼 클래스 레퍼런스를 서브 클래스 레퍼런스로 변환 

다운캐스팅을 하면 하면 자식 클래스의 객체 전체에 접근 가능하고 명시적으로 타입 변환을 지정해야한다

Person p = new Studnet("ho"); // 업캐스팅
Student s = (Student)p; // 다운캐스팅

 

instanceof 연산자

 

업캐스팅을 한 경우에는 레퍼런스가 가리키는 객체의 진짜 클래스 타입을 구분하기가 어렵다

instance of 연산자를 사용하면 t/f로 레퍼런스가 가리키는 객체가 해당 클래스 타입이면 true를 아니면 false를 리턴한다

Person jee = new Professor();
if (jee instance of Person)
if (jee instance of Student)

 

위처럼 if (객체 instance of 클래스) 형태로 사용한다

 

메소드 오버라이딩

부모의 메서드를 재정의한다, 메서드를 재정의햇을때는 

업캐스팅을 한 경우에도 자식에서 재정의한 메서드를 호출한다, 이 과정을 동적 바인딩이라고 한다

동적 바인딩을 실행시에 실행할 메서드를 결정해서 오버라이딩된 메서드가 항상 실행되도록 보장한다

Shaper shape = new Line();
shape.draw();

Line 클래스에서 draw 메서드를 재정의해둿으면 업캐스팅이 된 shape에서 draw를 호출하면

line의 draw()를 호출한 것 같이 된다

 

오버라이딩을 통해서 하나의 인터페이스에 서로 다른 내용을 구현하는 다형성을 실현한다

 

@Override 어노테이션을 붙여서 사용, private나 final로 선언시 서브 클래스에서 오버라이딩이 불가능하고

슈퍼 클래스 메서드 접근 지정자 보다 접근 범위를 줄여서 오버라이딩 할 수 없다

 

super.메서드로 슈퍼 클래스의 메서드를 자식 클래스에서 호출할 수도 있다

 

오버로딩과 오버라이딩

 

오버라이딩은 서브 클래스에서 슈퍼 클래스의 메서드와 동일한 이름의 메서드를 재작성

메서드명, 매개변수, 리턴타입이 모두 동일해야 성립

동적 바인딩으로 런타임에 결정

 

오버로딩은 이름이 같은 메서드를 중복해서 작성하고

메서드명은 동일. 매개변수 타입이나 갯수는 달라야된다

정적 바인딩으로 컴파일시에 결정된다

 

 

추상 클래스

추상 메서드 - 추상 메서드란 선언은 되어 있으나 코드가 구현되지 않은 메서드, 내부 구현이 되어있지 않다

메서드에 abstract를 붙여서 선언한다

추상 클래스 내에 일반 메서드와 추상 메서드를 섞어서 사용해도 된다

추상 메서드를 가지고 있으면 반드시 추상 클래스로 선언해야한다

추상 클래스는 미완성 상태의 추상 메서드가 있기에 객체로 선언 불가능하다

추상 클래스를 단순히 상속받고 메서드를 재정의 하지 않는 서브 클래스는 추상 클래스가 된다

 

 

추상 클래스를 상속받는 클래스는 반드시 추상 메서드를 오버라이딩해야한다, 이를 통해 다형성을 실행할 수 있다

이걸 왜쓰냐 - 설계와 구현을 분리!

 

 

인터페이스

 

interface 키워드로 선언, 인터페이스도 추상 클래스와 비슷하게 객체를 생성할 수 없고, 레퍼런스 변수로 선언 가능하다

인터페이스를 상속받아서 클래스를 작성하면 인터페이스의 모든 추상 메서드를 구현해야 한다.

 

인터페이스는 implements 키워드를 사용해서 모든 추상 메서드를 구현한 클래스로 작성한다

인터페이스끼리만 계속해서 상속이 가능하고 클래스에는 implements 로 구현해야한다

class A implements AImpl, Bimpl 등 여러 인터페이스를 구현 가능하다

 

인터페이스를 두는 목적은 다형성을 실현하기 위해서 사용

 

 

인터페이스와 추상 클래스 비교

 

인터페이스와 추상 클래스는 객체 생성 불가능, 다형성을 실현 하는 공통점이 있다

 

추상 클래스에는 추상 메서드와 일반 메서드 둘다 사용 가능, 변수 필드가 사용가능하지만

인터페이스는 상수, 메서드만 사용 가능하고 다중 상속을 지원하는 차이점이 있다

 

이어서 문제 풀어보자..

 

실습 1,2 번

import java.awt.*;
import java.util.*;

class TV {
    private int size;
    public TV(int size){this.size = size;}

    protected int getSize(){return size;}
}

class ColorTV extends TV{
    private int resolution;
    public ColorTV(int size, int resolution){
        super(size);
        this.resolution = resolution;
    }

    protected int getResolution(){
        return resolution;
    }

    public void printProperty(){
        System.out.print(getSize()+"인치 "+getResolution()+"컬러");
    }
}

class IPTV extends ColorTV{
    private String ip;

    public IPTV(String ip, int size, int resolution) {
        super(size, resolution);
        this.ip = ip;
    }

    public String getip(){
        return ip;
    }

    public void printProperty(){
        System.out.print("나의 IPTV는 " + getip() + " 주소의 ");
        super.printProperty();
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        IPTV myTv = new IPTV("192.1.1.2" ,32,1024);
        myTv.printProperty();
    }
}

 

10번

import java.util.*;

abstract class Pairmap {
    protected String keyArray[];
    protected String valueArray[];
    abstract String get(String key);
    abstract void put(String key, String value);
    abstract String delete(String key);
    abstract int length();
}

class Dictionary extends  Pairmap{

    int len;
    String[] keys, values;
    Dictionary(int len){
        this.len = len;
        keys = new String[len];
        values = new String[len];
    }
    @Override
    String get(String key) {
        for (int i = 0; i < length(); i++){
            if (keys[i].equals(key)){
                return values[i];
            }
        }
        return  null;
    }

    @Override
    void put(String key, String value) {
        for (int i = 0; i < length(); i++){
            if (keys[i] == null){
                keys[i] = key;
                values[i] = value;
                return;
            }
            else if (keys[i].equals(key)) {
                values[i] = value;
                return;
            }
        }
    }

    @Override
    String delete(String key) {
        for (int i = 0; i < length(); i++){
            if (keys[i].equals(key)) {
                if (values[i] != null) {
                    values[i] = null;
                    return key;
                }
            }
        }
        return null;
    }

    @Override
    int length() {
        return len;
    }
}




public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        Dictionary dlc = new Dictionary(10);
        dlc.put("황기태", "자바");
        dlc.put("이재문", "파이썬");
        dlc.put("이재문", "C++");
        System.out.println("이재문의 값은 " + dlc.get("이재문"));
        System.out.println("황기태의 값은 " + dlc.get("황기태"));
        dlc.delete("황기태");
        System.out.println("황기태의 값은 " + dlc.get("황기태"));

    }
}

 

11

문자열을 좀더 이쁘게 자르는 방식이 있을 것 같다..

import java.util.*;

abstract class Calc{
    int a,b;

    Calc(int a, int b){
        this.a = a;
        this.b = b;
    }

    abstract int calculate();
}

class Add extends  Calc{


    Add(int a, int b) {
        super(a, b);
    }

    @Override
    int calculate() {
        return a + b;
    }
}

class Minus extends Calc{
    Minus(int a, int b) {
        super(a, b);
    }
    @Override
    int calculate() {
        return a - b;
    }
}

class Mul extends Calc{

    Mul(int a, int b) {
        super(a, b);
    }

    @Override
    int calculate() {
        return a*b;
    }
}

class Div extends Calc{
    Div(int a, int b) {
        super(a, b);
    }

    @Override
    int calculate() {
        return b != 0 ? a/b : 0;
    }
}


public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a,b;
        char type;
        String input;
        System.out.print("두 정수와 연산자를 입력하시오 ");
        input = in.nextLine();
        a = Integer.parseInt(input.substring(0,1));
        b = Integer.parseInt(input.substring(2,3));
        type = input.charAt(4);
        if (type == '+'){
            Add add = new Add(a,b);
            System.out.println(add.calculate());
        }
    }
}

 

12번

import java.util.*;

interface Shape {
    final double PI = 3.14;

    void draw();

    double getArea();

    default public void redraw() {
        System.out.print("=== 다시 그립니다. === ");
        draw();
    }
}

class Circle implements Shape{

    int len;

    Circle(int len){
        this.len = len;
    }

    @Override
    public void draw() {
        System.out.println("반지름이 " + len + " 인 원입니다.");
    }

    @Override
    public double getArea() {
        return len * len * PI ;
    }
}


public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        Shape donut = new Circle(10);
        donut.redraw();
        System.out.println("면적은 " + donut.getArea());

    }
}

'명품 자바' 카테고리의 다른 글

명품자바 7장 제네릭,컬렉션  (1) 2023.12.31
명품자바 6장 모듈, 패키지  (1) 2023.12.31
명품자바 4장  (1) 2023.12.23
가비지 발생시점  (0) 2023.11.17