what is polymorphism java tutorial with examples
이 자습서에서는 Java의 다형성이 무엇인지, 다형성 유형 및 예제를 통해 컴파일 타임 다형성을 구현하는 방법을 설명합니다.
'다형성'이라는 단어는 두 단어 즉, 'Poly' 많은 것을 의미하고“ 변경해 ”의미 형태. 따라서 다형성은 다양한 형태를 의미합니다. 프로그래밍 언어에서는 객체가 다양한 형태를 취할 수 있으므로 객체가 다형성이라고 말할 수 있습니다.
다형성은 OOP의 가장 중요한 기능 중 하나이며 다양한 형태로 기능 (객체, 메시지 또는 메서드 또는 연산자)을 표현할 수 있습니다.
=> 여기에서 Java Beginners Guide를 살펴보십시오.
학습 내용 :
Java의 다형성 소개
다형성 엔티티는 다른 시나리오에서 다르게 작동합니다.
예를 들면 Java에서 '+'(더하기) 연산자를 고려하십시오. 이것은 이항 연산자이며 두 개의 피연산자를 사용합니다. '+'연산자에 전달 된 피연산자가 숫자이면 두 숫자의 합을 반환하는 더하기 연산이 수행됩니다.
피연산자가 문자열 유형으로 변경되면‘+’연산자는 문자열 개체를 추가하지 않지만 문자열의 내용을 연결하거나 결합하여 결과 세 번째 문자열을 형성합니다.
예를 들면 만약 ' 하나 ”및“ 두 ”는 두 개의 String 객체의 내용입니다. '하나'+ '둘' 결과는 ' 하나 둘 ”. 이것은 연결입니다.
Java에서 모든 객체는 'Object'클래스에서 파생되므로 다형성이어서 Object 클래스와의 'IS-A'관계를 충족합니다.
객체는 항상 특정 클래스 유형의 참조 변수를 통해 액세스됩니다. 특정 유형의 참조 변수가 선언되면 수정할 수 없습니다. 그러나 참조 변수가 'Final'로 선언되지 않은 경우 다른 개체를 가리 키도록 다시 할당 할 수 있습니다.
이 개체 참조의 유형은 호출해야하는 클래스 메서드 또는 함수를 결정합니다.
예를 들면ABC 클래스와 ABC에서 파생 된 클래스 XYZ가있는 경우 두 클래스 모두 다형성 메서드 func ()를 갖습니다.
class ABC{ void func(){} } class XYZ extends ABC{ void func() {} }
ABC 유형의 참조를 만들어 보겠습니다.
obj = new XYZ ();
이제 func () 메서드를 호출하면 obj가 가리키는 객체가 XYZ 클래스이므로 XYZ 클래스의 func () 메서드가 호출됩니다.
위의 예에서 보았 듯이 func () 메서드는 구현이 다르지만 프로토 타입은 동일합니다. 참조 객체가 가리키는 객체에 따라 해당 시나리오에서 적절한 구현이 호출됩니다. 이것은 다형성입니다.
Java의 다형성에 대해 자세히 살펴 보겠습니다.
자바 다형성 예제
앞에서 설명한 추가 작업을 통해 Java에서 다형성의 간단한 예를 이해하겠습니다.
여기서는 이름은 같지만 매개 변수가 다른 두 가지 방법을 사용합니다. 첫 번째 함수는 두 개의 정수 매개 변수를 허용하고 두 번째 방법은 두 개의 문자열 매개 변수를 허용합니다.
전달 된 매개 변수의 유형에 따라 적절한 메소드가 호출되고 두 개의 정수를 추가하고 결과를 인쇄하거나 두 문자열을 연결하고 결과 문자열을 인쇄합니다.
Java 프로그램은 다음과 같습니다.
class Addition_operation{ //method to add two integers void addition_func(int num1,int num2){ System.out.println('ABC::addition_func:' + (num1+num2)); } //overloaded method to add two strings void addition_func(String str1, String str2){ String result = str1 + ' ' + str2; System.out.println('XYZ::addition_func:' + result); } } public class Main { public static void main(String() args) { Addition_operation abc = new Addition_operation(); //create a class object abc.addition_func (3,4); //calls 1st method abc.addition_func ('Hello' , 'World!'); //calls 2nd method } }
산출:
여기서 우리는 처음 두 개의 정수 매개 변수를 addition_func에 전달할 때 첫 번째 메소드가 호출되는 것을 보았습니다. 두 번째 함수 호출에서 두 개의 String 유형 매개 변수를 전달하므로 두 번째 오버로드 된 메소드가 호출됩니다.
다형성의 유형
Java는 두 가지 유형의 다형성을 지원합니다.
- 컴파일 타임 다형성
- 런타임 다형성
이름에서 알 수 있듯이 컴파일 타임 다형성은 컴파일 타임에 수행되고 런타임 다형성은 런타임에 수행됩니다.
위의 그림과 같이 Compile-time polymorphism은 Overloading을 통해 구현됩니다. 메서드 나 연산자를 오버로드 할 수 있습니다. 런타임 다형성은 재정의를 통해 달성됩니다.
이 튜토리얼에서는 컴파일 타임 다형성에 대해 자세히 설명합니다. 다음 튜토리얼에서 런타임 다형성을 다룰 것입니다.
자바의 컴파일 시간 다형성
컴파일 타임 다형성은 '정적 다형성'이라고도합니다. 컴파일 타임 다형성의 일부로 수행되는 다형성은 컴파일 타임에 수행됩니다.
Java에서 컴파일 타임 다형성은“ 메서드 오버로딩 ”. 메서드 오버로딩을 사용하면 동일한 이름을 가진 하나 이상의 메서드를 가질 수 있으며 매개 변수의 숫자 나 유형 또는 순서 만 구분할 수 있습니다.
메서드 오버로딩은 Java에서 컴파일 타임 다형성의 가장 일반적인 구현입니다. Java는 연산자 오버로딩도 지원합니다.
일반적으로 Java에서 오버로딩이란 무엇입니까?
Java에서 오버로딩은 이름과 반환 유형이 같지만 인수의 순차, 수 및 유형이 다른 둘 이상의 메소드를 갖는 프로세스입니다. 일반적으로 메서드 오버로딩이라고도합니다.
자바에서 메서드 오버로딩
메서드 오버로딩은 Java에서 컴파일 타임 다형성을 구현 한 것입니다. 동일한 이름 및 / 또는 반환 유형을 가진 하나 이상의 메서드가 있지만 매개 변수 목록이 다른 경우 메서드가 '오버로드'되었다고 말합니다.
따라서 주어진 클래스에서 이름은 같지만 인수 목록이 다른 다양한 메서드를 가질 수 있습니다.
오버로드 된 메서드를 어떻게 호출합니까? 아니면 컴파일러가 어떤 메서드가 호출되는지 어떻게 알 수 있습니까?
매개 변수 목록에 따라 호출과 일치하는 정확한 메소드 호출이 수행됩니다.
우리는 Java의 클래스가 하나 이상의 생성자를 가질 수 있음을 이미 보았습니다. 생성자의 경우 모든 생성자에서 인수 목록 또는 생성자가 허용하는 인수가 다릅니다. 이것은 과부하의 예입니다. 따라서 생성자 오버로딩은 Java에서 메서드 오버로딩의 기본 형식입니다.
이제 Java에서 메서드를 오버로드하는 방법을 살펴 보겠습니다.
Java는 매개 변수 / 인수 목록의 변형에 따라 세 가지 메소드 오버로딩 방법을 제공합니다.
# 1) 매개 변수 유형
매개 변수의 데이터 유형에 따라 Java에서 메소드를 오버로드 할 수 있습니다.
세 가지 방법의 프로토 타입을 제공 한 다음 예제를 고려하십시오.
더하기 (int, int);
더하기 (int, float);
더하기 (문자열, 문자열);
위에서 볼 수 있듯이 세 가지 경우 모두 동일한 메서드 이름과 동일한 수의 매개 변수를 갖지만 각 메서드 호출에는 다른 유형의 매개 변수가 있습니다.
따라서 메서드에 다른 유형의 매개 변수가있는 한 메서드가 오버로드되었다고 말할 수 있습니다. 메소드를 호출 할 때 컴파일러는 매개 변수의 데이터 유형을 결정하고 메소드 호출과 함께 제공된 매개 변수 목록의 데이터 유형에 따라 적절한 메소드가 호출됩니다.
예를 들면아래와 같은 메서드 호출이있는 경우 :
추가 (3, 3.5);
위의 메소드 호출에서 첫 번째 매개 변수는 int 유형이고 두 번째 매개 변수는 float 유형임을 알 수 있습니다. 위의 호출이 발생하면 컴파일러는 매개 변수 목록을 확인한 다음 위의 두 번째 메서드 인 적절한 메서드를 호출합니다.
이제 매개 변수의 데이터 유형을 기반으로 메소드 오버로딩을 보여주기 위해 완전한 Java 프로그램을 구현해 보겠습니다.
class MethodOverload { //overloaded method - char parameter public void printParam(char ch) { System.out.println('Input character:' + ch); } //overloaded method - int parameter public void printParam(int num) { System.out.println('Input Number:' + num); } } class Main { public static void main(String args()) { MethodOverload obj = new MethodOverload(); obj.printParam('A'); //call overloaded method (char ) obj.printParam(10); //call overloaded method (int ) } }
산출:
# 2) 매개 변수 수
메서드 오버로딩의 또 다른 구현은 함수 호출에서 다른 수의 매개 변수로 메서드를 오버로딩하는 것입니다.
예를 들면다음 메서드 선언을 고려해 보겠습니다.
addnum (int, int);
addnum (int, int, int);
위의 메서드 선언에서 첫 번째 메서드 선언에는 두 개의 매개 변수가 있고 두 번째 선언에는 세 개의 매개 변수가 있습니다. 함수가 호출되면 컴파일러는 매개 변수 수를 검사 한 다음 메서드 호출을 적절하게 해결합니다.
아래 예제는 매개 변수 수에 따라 메소드 오버로딩을 사용하는 프로그램을 보여줍니다.
class MethodOverload { //overloaded method - 1 parameter public void printParam(char ch) { System.out.println(ch); } //overloaded method - 2 parameters public void printParam(char ch, int num) { System.out.println('Character: ' + ch + ' ; '+ 'Number:' +num); } } class Main { public static void main(String args()) { MethodOverload obj = new MethodOverload(); obj.printParam('A'); //call overloaded method (1 ) obj.printParam('A',10); //call overloaded method (2 ) } }
산출:
이 예에서는 매개 변수 수에 따라 오버로드 된 두 가지 메서드가 있습니다. 첫 번째 방법은 하나의 매개 변수를 사용하고 두 번째 방법은 두 개의 매개 변수를 사용합니다. 메인 메서드에서 두 메서드를 차례로 호출하고 컴파일러는 지정된 매개 변수 수에 따라 함수 호출을 해결합니다.
# 3) 매개 변수 순서
메서드 오버로딩을 구현하는 세 번째 접근 방식은 오버로드 된 메서드의 매개 변수 시퀀스를 기반으로합니다.
다음 메서드 선언 예제를 고려하십시오.
sum (int, float);
sum (float, int);
여기에 오버로드 된 메서드 합계가 있습니다. 첫 번째 선언에서 매개 변수는 int 및 float입니다. 두 번째 선언에서도 매개 변수는 int 및 float이지만 매개 변수 목록의 순서가 변경됩니다.
이제 float 매개 변수가 먼저 표시되고 int 매개 변수가 두 번째입니다. 매개 변수 순서를 변경하여 메소드 오버로딩을 수행 할 수 있습니다.
그만큼 아래 Java 프로그램이 이것을 보여줍니다.
class MethodOverload { //overloaded method - char,int parameter public void printParam(char ch, int num) { System.out.println('Input character:' + ch + ' ; ' + 'Input Number:' + num); } //overloaded method - int,char parameter public void printParam(int num, char ch) { System.out.println('Input Number:' + num + ' ; ' + 'Input Character:' + ch); } } class Main { public static void main(String args()) { MethodOverload obj = new MethodOverload(); obj.printParam('A', 100); //call overloaded method (char,int) obj.printParam(100, 'A'); //call overloaded method (int,char) } }
산출:
Java jar 파일 실행 방법
위의 프로그램에는 두 개의 메서드 선언에서 순서가 변경된 int 및 char 매개 변수가있는 printParam 오버로드 된 메서드가 있습니다.
메서드 오버로딩의 잘못된 사례
지금까지 매개 변수 목록을 사용한 메소드 오버로딩에 대해 논의했습니다. 메소드의 반환 유형은 아직 고려하지 않았습니다. 반환 유형을 기반으로 메서드를 오버로드하지 않습니다.
예를 들어 두 메서드가 이름과 매개 변수 목록은 같지만 반환 유형이 다른 경우이 두 메서드가 오버로드되었다고 말하지 않습니다. 이 경우는 과부하로 인해 무효가됩니다.
따라서 다음과 같은 선언이있는 경우 :
I int (int, int);
문자열 sum (int, int);
이 경우 두 메서드가 오버로드되지 않았으므로 컴파일러에서 오류가 발생합니다. 따라서 반환 유형에만 기반하여 메서드가 구분되지 않습니다.
Java 프로그램을 사용하여이 유효하지 않은 경우를 보여 드리겠습니다.
class OverloadDemo { public double myMethod(int num1, int num2) { System.out.println('OverloadDemo::myMethod returns double'); return num1+num2; } public int myMethod(int var1, int var2) { System.out.println('OverloadDemo::myMethod returns int'); return var1-var2; } } class Main { public static void main(String args()) { OverloadDemo obj2= new OverloadDemo(); obj2.myMethod(10,10); obj2.myMethod(20,12); } }
위의 프로그램에서 myMethod 메소드에는 두 개의 프로토 타입이 있습니다. 하나의 프로토 타입은 두 개의 int 매개 변수를 취하고 double을 반환합니다. 두 번째 메서드 프로토 타입은 두 개의 int 매개 변수를 취하고 int를 반환합니다.
따라서이 프로그램을 컴파일하면 아래와 같은 결과가 나옵니다.
산출:
위의 컴파일 오류는 메서드가 두 번 선언되었음을 나타냅니다. 이는 컴파일러가 단순히 반환 유형에 따라 오버로드 된 이러한 메서드를 고려하지 않음을 의미합니다.
연산자 오버로딩
연산자 오버로딩은 기존 연산자에 다른 의미가 부여되는 오버로딩 메커니즘입니다.
이 자습서의 소개 섹션에서 설명했듯이 더하기 연산자 '+'는 연산자 오버로딩의 전형적인 예입니다.
이 연산자의 피연산자가 숫자이면 + 연산자는 두 값의 합계를 반환합니다. 그러나 피연산자가 String 유형이면 더하기 연산의 결과는 연결된 문자열입니다. Java에서는 + (더하기) 연산자 만 오버로드 할 수 있습니다.
이 연산자는 두 가지 기능을 수행합니다.
- 정수 또는 숫자 값 추가.
- 문자열 연결
따라서 연산자 오버로딩 지원은 C ++와 달리 Java에서 제한되며 sizeof, 도트 연산자 등과 같은 몇 가지를 제외하고 거의 모든 연산자를 오버로드 할 수 있습니다.
아래 프로그램은 Java에서 연산자 오버로딩을 보여줍니다.
class OperatorOverload { //overloaded method for concatenating two strings void operator(String str1, String str2) { String resultStr = str1 + str2; System.out.println('Concatenated String: ' + resultStr); } //overloaded method for adding two numbers void operator(int num1, int num2) { int result = num1 + num2; System.out.println('Sum of two numbers : ' + result); } } class Main { public static void main(String() args) { OperatorOverload obj = new OperatorOverload(); obj.operator(10, 15); //add two numbers obj.operator('Hello ', 'World!!'); //concatenate two strings } }
산출:
위의 프로그램에서는‘+’연산자를 오버로드했습니다. 오버로드 된 메서드에 두 개의 정수 값을 전달하면 두 정수의 합계가 반환되고 두 개의 문자열이 전달되면 결과는 연결된 문자열이됩니다.
오버로딩 및 컴파일 타임 다형성과 관련하여 주목해야 할 사항입니다.
- 메서드 오버로딩은 정적 다형성이라고도하는 컴파일 타임 다형성을 구현하는 방법입니다.
- 정적 다형성은 초기 바인딩 또는 컴파일 타임 바인딩이라고도합니다.
- 매개 변수와 함수 호출의 바인딩이 컴파일 타임에 발생하므로 오버로딩을 컴파일 타임 바인딩이라고합니다.
- Java에서는 '+'연산자 만 오버로드 할 수 있으며 두 개의 정수를 더하거나 두 문자열을 연결합니다.
자주 묻는 질문
Q # 1) Java에서 다형성이 필요한 이유는 무엇입니까?
대답: 다형성은 우리가 하나의 객체에 대해 많은 구현을 할 수있게합니다. 메서드 오버로딩을 통해 기억하기 어려운 이름이 다른 메서드를 너무 많이 가질 필요가 없습니다. 대신 오버로드 된 메서드를 사용하여 유사한 기능을 수행하는 메서드를 명확하게 구현할 수 있습니다.
또한 재정의는 기존 클래스에 더 많은 기능을 더 쉽게 추가 할 수있는 적절한 상속 구현을 지원합니다.
Q # 2) 다형성 OOP 란 무엇입니까?
대답: 다형성의 객체 지향 프로그래밍 정의는 프로그래밍 언어가 다양한 형태로 하나의 객체를 구현하는 능력을 나타냅니다. 다형성은 또한 추가 기능을 갖도록 부모 클래스의 메서드를 파생 클래스로 재정의하는 프로그램의 기능으로 정의됩니다.
Q # 3) main 메서드를 오버로드하고 재정의 할 수 있습니까?
대답: 아니요. 정적 기본 메서드를 재정의 할 수 없습니다. main 메소드를 오버로드 할 수 있지만 JVM은 오버로드 된 main 메소드를 호출하지 않습니다. 따라서 가장 좋은 대답은 main 메서드를 오버로드하거나 재정의하지 않는 것입니다.
Q # 4) 생성자가 오버로드 될 수 있습니까?
대답: 예, Java 메서드를 오버로드하는 것과 같은 방식으로 Java에서 생성자를 오버로드 할 수 있습니다. 생성자는 일반적으로 이름은 같지만 인수 수가 다릅니다.
Q # 5) 메서드 오버로딩이 유용한 이유는 무엇입니까?
대답: 메서드 오버로딩을 사용하여 깔끔한 코드를 작성할 수 있으며 동일한 이름의 메서드가 있으므로 읽을 수있게됩니다. 따라서 다양한 데이터 유형에 대한 기능을 구현하는 경우 메서드를 오버로드 할 수 있으며 코드를 더 쉽게 분리 할 수 있습니다.
결론
Java의 다형성은 객체가 다양한 형태를 가질 수 있음을 의미합니다. Java의 다형성에는 컴파일 타임 다형성과 런타임 다형성의 두 가지 유형이 있습니다. 컴파일 타임 다형성은 컴파일 타임에 수행됩니다. 컴파일 타임 다형성은 정적이며 메서드 오버로딩 및 연산자 오버로딩을 통해 구현됩니다.
런타임 다형성은 런타임에 수행되며 동적입니다. 메서드 재정의를 사용하여 구현됩니다.
이 자습서에서는 메서드 오버로딩을 구현하는 방법을 살펴 보았습니다. 연산자 오버로딩에 대해서도 자세히 설명했습니다. Java는‘+’연산자의 오버로딩 만 지원합니다.