CodeGym/Java Blog/무작위의/자바 다형성
John Squirrels
레벨 41
San Francisco

자바 다형성

무작위의 그룹에 게시되었습니다
회원
OOP 관련 질문은 IT 회사의 Java 개발자 위치에 대한 기술 인터뷰의 필수적인 부분입니다. 이 기사에서 우리는 OOP의 한 가지 원칙인 다형성에 대해 이야기할 것입니다. 인터뷰 중에 자주 묻는 측면에 초점을 맞추고 명확성을 위해 몇 가지 예를 제공합니다.

Java의 다형성이란 무엇입니까?

다형성은 객체의 특정 유형에 대한 정보 없이 동일한 인터페이스를 가진 객체를 동일한 방식으로 처리하는 프로그램의 기능입니다. 다형성이 무엇인지에 대한 질문에 대답하는 경우 의미하는 바를 설명하라는 요청을 받을 가능성이 큽니다. 많은 추가 질문을 유발하지 않고 다시 한 번 면접관을 위해 모든 것을 배치하십시오. 인터뷰 시간: Java의 다형성 - 1OOP 접근 방식에는 클래스를 기반으로 하는 개체 간의 상호 작용을 기반으로 Java 프로그램을 빌드하는 작업이 포함된다는 사실부터 시작할 수 있습니다. 클래스는 프로그램에서 개체를 만드는 데 사용되는 이전에 작성된 청사진(템플릿)입니다. 또한 클래스에는 항상 특정 유형이 있으며 좋은 프로그래밍 스타일을 사용하면 해당 목적을 제안하는 이름이 있습니다. 또한 Java는 강력한 형식이므로 프로그램 코드는 변수를 선언할 때 항상 개체 형식을 지정해야 합니다. 여기에 엄격한 타이핑이 코드 보안과 안정성을 향상시키고 컴파일 시에도 호환되지 않는 유형(예: 문자열을 숫자로 나누기 시도)으로 인한 오류를 방지할 수 있다는 사실을 추가합니다. 당연히 컴파일러는 "알고" 있어야 합니다. 선언된 유형 – JDK의 클래스이거나 우리가 직접 만든 클래스일 수 있습니다. 면접관에게 우리 코드는 선언에 표시된 유형의 객체뿐만 아니라 그 자손도 사용할 수 있음을 지적하십시오.이것은 중요한 점입니다. 여러 유형을 단일 유형으로 사용할 수 있습니다(이러한 유형이 기본 유형에서 파생된 경우). 이는 또한 유형이 슈퍼클래스인 변수를 선언하면 해당 변수에 하위 항목 중 하나의 인스턴스를 할당할 수 있음을 의미합니다. 예를 들면 면접관이 좋아할 것입니다. 여러 클래스(기본 클래스)에서 공유할 수 있는 일부 클래스를 선택하고 그 중 몇 개가 상속하도록 합니다. 기본 클래스:
public class Dancer {
    private String name;
    private int age;

    public Dancer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void dance() {
        System.out.println(toString() + " I dance like everyone else.");
    }

    @Override
    public String toString() {
        Return "I'm " + name + ". I'm " + age + " years old.";
    }
}
하위 클래스에서 기본 클래스의 메서드를 재정의합니다.
public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString () + " I dance the electric boogie!");
    }
}

public class Breakdancer extends Dancer {

    public Breakdancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString() + " I breakdance!");
    }
}
다형성의 예와 이러한 개체가 프로그램에서 사용되는 방법:
public class Main {

    public static void main(String[] args) {
        Dancer dancer = new Dancer("Fred", 18);

        Dancer breakdancer = new Breakdancer("Jay", 19); // Widening conversion to the base type
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20); // Widening conversion to the base type

        List<dancer> disco = Arrays.asList(dancer, breakdancer, electricBoogieDancer);
        for (Dancer d : disco) {
            d.dance(); // Call the polymorphic method
        }
    }
}
주요 방법 에서 다음 행을 보여줍니다.
Dancer breakdancer = new Breakdancer("Jay", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20);
수퍼클래스의 변수를 선언하고 하위 클래스 중 하나의 인스턴스인 객체를 할당합니다. 대부분 할당 연산자의 왼쪽과 오른쪽에 선언된 유형의 불일치로 인해 컴파일러가 뒤집히지 않는 이유를 물을 것입니다. 결국 Java는 강력한 유형입니다. 확장 유형 변환이 여기서 작동한다고 설명합니다. 개체에 대한 참조는 기본 클래스에 대한 참조처럼 취급됩니다. 또한 코드에서 이러한 구성을 만나면 컴파일러는 자동으로 암시적으로 변환을 수행합니다. 샘플 코드는 할당 연산자( Dancer ) 의 왼쪽에 선언된 유형이 오른쪽 ( Breakdancer , ElectricBoogieDancer ) 에 선언된 여러 형식(유형)을 가지고 있음을 보여줍니다.). 각 양식은 수퍼클래스( 댄스 메서드) 에 정의된 일반 기능과 관련하여 고유한 동작을 가질 수 있습니다 . 즉, 상위 클래스에서 선언된 메서드는 하위 클래스에서 다르게 구현될 수 있습니다. 이 경우에 우리는 메소드 오버라이딩을 다루고 있는데, 이는 정확히 여러 폼(동작)을 생성하는 것입니다. 이는 메인 메서드에서 코드를 실행하여 볼 수 있습니다. 프로그램 출력: I'm Fred. 저는 18 살입니다. 나는 다른 사람들처럼 춤을 춥니다. 저는 제이입니다. 나는 19 살입니다. 나는 브레이크 댄스를 춘다! 저는 마르시아입니다. 내 나이는 20 살입니다. 나는 일렉트릭 부기를 춘다! 하위 클래스의 메서드를 재정의하지 않으면 다른 동작이 발생하지 않습니다. 예를 들어,ElectricBoogieDancer 클래스의 경우 프로그램의 출력은 다음과 같습니다. I'm Fred. 저는 18 살입니다. 나는 다른 사람들처럼 춤을 춥니다. 저는 제이입니다. 나는 19 살입니다. 나는 다른 사람들처럼 춤을 춥니다. 저는 마르시아입니다. 내 나이는 20 살입니다. 나는 다른 사람들처럼 춤을 춥니다. 이는 BreakdancerElectricBoogieDancer 클래스를 만드는 것이 의미가 없다는 것을 의미합니다 . 다형성의 원리는 구체적으로 어디에 명시되어 있습니까? 특정 유형에 대한 지식 없이 프로그램에서 사용되는 개체는 어디에 있습니까? 이 예제에서는 Dancer d 개체에서 dance() 메서드가 호출될 때 발생합니다 . Java에서 다형성이란 프로그램이 객체가 객체인지 여부를 알 필요가 없음을 의미합니다. Breakdancer 또는 ElectricBoogieDancer . 중요한 것은 Dancer 클래스 의 후손이라는 것입니다 . 그리고 자손을 언급하는 경우 Java의 상속은 extends 뿐만 아니라 구현. 이제 Java가 다중 상속을 지원하지 않는다는 점을 언급할 때입니다. 각 유형은 하나의 부모(슈퍼클래스)와 무제한의 자손(서브클래스)을 가질 수 있습니다. 따라서 인터페이스는 여러 기능 집합을 클래스에 추가하는 데 사용됩니다. 하위 클래스(상속)와 비교할 때 인터페이스는 상위 클래스와 덜 결합됩니다. 그들은 매우 널리 사용됩니다. Java에서 인터페이스는 참조 유형이므로 프로그램은 인터페이스 유형의 변수를 선언할 수 있습니다. 이제 예를 들어볼 차례입니다. 인터페이스 만들기:
public interface CanSwim {
    void swim();
}
명확성을 위해 관련 없는 다양한 클래스를 가져와서 인터페이스를 구현하도록 합니다.
public class Human implements CanSwim {
    private String name;
    private int age;

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public void swim() {
        System.out.println(toString()+" I swim with an inflated tube.");
    }

    @Override
    public String toString() {
        return "I'm " + name + ". I'm " + age + " years old.";
    }

}

public class Fish implements CanSwim {
    private String name;

    public Fish(String name) {
        this.name = name;
    }

    @Override
    public void swim() {
        System.out.println("I'm a fish. My name is " + name + ". I swim by moving my fins.");

    }

public class UBoat implements CanSwim {

    private int speed;

    public UBoat(int speed) {
        this.speed = speed;
    }

    @Override
    public void swim() {
        System.out.println("I'm a submarine that swims through the water by rotating screw propellers. My speed is " + speed + " knots.");
    }
}
주요 방법:
public class Main {

    public static void main(String[] args) {
        CanSwim human = new Human("John", 6);
        CanSwim fish = new Fish("Whale");
        CanSwim boat = new UBoat(25);

        List<swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
인터페이스에 정의된 다형성 메서드를 호출한 결과는 이 인터페이스를 구현하는 유형의 동작 차이를 보여줍니다. 우리의 경우 이들은 swim 메서드 에 의해 표시되는 다른 문자열입니다 . 우리의 예제를 공부한 후 면접관은 왜 이 코드를 메인 메서드 에서 실행하는지 물을 수 있습니다.
for (Swim s : swimmers) {
            s.swim();
}
하위 클래스에 정의된 재정의 메서드가 호출되도록 합니까? 프로그램이 실행되는 동안 메소드의 원하는 구현은 어떻게 선택됩니까? 이러한 질문에 답하려면 후기(동적) 바인딩을 설명해야 합니다. 바인딩이란 메서드 호출과 해당 특정 클래스 구현 간의 매핑을 설정하는 것을 의미합니다. 본질적으로 코드는 클래스에 정의된 세 가지 메서드 중 실행될 메서드를 결정합니다. Java는 기본적으로 후기 바인딩을 사용합니다. 즉, 초기 바인딩의 경우처럼 컴파일 타임이 아니라 런타임에 바인딩이 발생합니다. 이것은 컴파일러가 이 코드를 컴파일할 때
for (Swim s : swimmers) {
            s.swim();
}
어떤 클래스( Human , Fish 또는 Uboat )에 수영 할 때 실행될 코드가 있는지 알 수 없습니다.메서드가 호출됩니다. 이는 동적 바인딩 메커니즘 덕분에 프로그램이 실행될 때만 결정됩니다(런타임에 개체 유형을 확인하고 이 유형에 대한 올바른 구현 선택). 이것이 어떻게 구현되는지 묻는다면 객체를 로드하고 초기화할 때 JVM이 메모리에 테이블을 만들고 변수를 값과 연결하고 객체를 메서드와 연결한다고 대답할 수 있습니다. 이 과정에서 클래스가 상속되거나 인터페이스를 구현하는 경우 가장 먼저 해야 할 일은 재정의된 메서드가 있는지 확인하는 것입니다. 있는 경우 이 형식에 바인딩됩니다. 그렇지 않은 경우 일치하는 메서드 검색은 한 단계 높은 클래스(부모)로 이동하는 식으로 다단계 계층 구조의 루트까지 이동합니다. OOP의 다형성과 코드에서의 구현에 관해서는 추상 클래스와 인터페이스를 사용하여 기본 클래스의 추상 정의를 제공하는 것이 좋습니다. 이 방법은 추상화 원칙(일반적인 동작 및 속성을 식별하여 추상 클래스에 넣거나 일반적인 동작만 식별하여 인터페이스에 넣기)을 따릅니다. 다형성을 구현하려면 인터페이스 및 클래스 상속을 기반으로 개체 계층 구조를 설계하고 생성해야 합니다. Java의 다형성 및 혁신과 관련하여 Java 8부터 추상 클래스 및 인터페이스를 만들 때 또는 일반적인 동작만 식별하고 인터페이스에 넣습니다. 다형성을 구현하려면 인터페이스 및 클래스 상속을 기반으로 개체 계층 구조를 설계하고 생성해야 합니다. Java의 다형성 및 혁신과 관련하여 Java 8부터 추상 클래스 및 인터페이스를 만들 때 또는 일반적인 동작만 식별하고 인터페이스에 넣습니다. 다형성을 구현하려면 인터페이스 및 클래스 상속을 기반으로 개체 계층 구조를 설계하고 생성해야 합니다. Java의 다형성 및 혁신과 관련하여 Java 8부터 추상 클래스 및 인터페이스를 만들 때기본 클래스의 추상 메서드에 대한 기본 구현을 작성하는 default 키워드입니다. 예를 들어:
public interface CanSwim {
    default void swim() {
        System.out.println("I just swim");
    }
}
때때로 면접관은 다형성 원칙이 위반되지 않도록 기본 클래스의 메서드를 선언해야 하는 방법에 대해 질문합니다. 대답은 간단합니다. 이러한 메서드는 static , private 또는 final 이 아니어야 합니다 . Private은 클래스 내에서만 메서드를 사용할 수 있도록 하므로 하위 클래스에서 재정의할 수 없습니다. 정적은 메서드를 객체가 아닌 클래스와 연결하므로 슈퍼클래스의 메서드가 항상 호출됩니다. 그리고 final은 메서드를 변경할 수 없고 하위 클래스에서 숨길 수 있도록 합니다.

다형성은 우리에게 무엇을 제공합니까?

또한 다형성이 우리에게 어떤 이점이 있는지에 대한 질문을 받을 가능성이 높습니다. 복잡한 세부 사항에 얽매이지 않고 간단히 대답할 수 있습니다.
  1. 클래스 구현을 대체할 수 있습니다. 테스트는 이를 기반으로 합니다.
  2. 확장성을 용이하게 하여 미래에 구축할 수 있는 기반을 훨씬 쉽게 만들 수 있습니다. 기존 유형을 기반으로 새 유형을 추가하는 것은 OOP 프로그램의 기능을 확장하는 가장 일반적인 방법입니다.
  3. 공통 유형 또는 동작을 공유하는 개체를 하나의 컬렉션 또는 배열로 결합하고 균일하게 처리할 수 있습니다(예제에서와 같이 모든 사람이 강제로 dance() 또는 swim() 을 수행하도록 했습니다 :)
  4. 새로운 유형 생성의 유연성: 부모의 메서드 구현을 선택하거나 하위 클래스에서 재정의할 수 있습니다.

일부 이별의 말

다형성은 매우 중요하고 광범위한 주제입니다. Java의 OOP에 대한 이 기사의 거의 절반의 주제이며 언어 기반의 상당 부분을 형성합니다. 인터뷰에서 이 원칙을 정의하는 것을 피할 수 없을 것입니다. 모르거나 이해가 안 되면 아마 면접이 끝날 것 같습니다. 그러니 게으르지 마십시오. 인터뷰 전에 지식을 평가하고 필요한 경우 새로 고치십시오.
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다