다형성 vs 오버라이드 vs 오버로드
Java에 관해서는 다음과 같이 질문합니다.
다형성이란 무엇인가?
오버로드 또는 오버라이드 중 어느 것이 허용 가능한 답변입니까?
나는 그것보다 조금 더 많은 것이 있다고 생각한다.
구현되지 않은 메서드를 정의한 추상 기본 클래스가 있고 하위 클래스에서 해당 메서드를 정의한 경우 여전히 오버라이드입니까?
오버로딩은 확실히 정답이 아니라고 생각합니다.
다형성을 표현하는 가장 명확한 방법은 추상 베이스 클래스(또는 인터페이스)를 사용하는 것입니다.
public abstract class Human{
...
public abstract void goPee();
}
는 추상적이기 입니다.왜냐하면goPee()
인간에게는 메서드를 정의할 수 없습니다.이는 남성과 여성 하위 분류에만 정의할 수 있습니다.또한 인간은 추상적인 개념입니다.남자도 여성도 아닌 인간을 만들 수 없습니다.둘 중 하나일 거야
따라서 추상 클래스를 사용하여 구현을 연기합니다.
public class Male extends Human{
...
@Override
public void goPee(){
System.out.println("Stand Up");
}
}
그리고.
public class Female extends Human{
...
@Override
public void goPee(){
System.out.println("Sit Down");
}
}
이제 인간들로 가득 찬 방 전체에 오줌을 싸라고 말할 수 있어
public static void main(String[] args){
ArrayList<Human> group = new ArrayList<Human>();
group.add(new Male());
group.add(new Female());
// ... add more...
// tell the class to take a pee break
for (Human person : group) person.goPee();
}
이를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
Stand Up
Sit Down
...
다형성은 클래스 인스턴스가 상속 트리의 다른 클래스 인스턴스(대부분 상위 클래스 중 하나)인 것처럼 동작할 수 있는 기능입니다.예를 들어 Java에서는 모든 클래스가 개체에서 상속됩니다.따라서 Object 유형의 변수를 만들고 모든 클래스의 인스턴스를 할당할 수 있습니다.
재정의는 다른 클래스에서 상속되는 클래스에서 발생하는 함수 유형입니다.오버라이드 함수는 기본 클래스에서 상속된 함수를 "대체"하지만 해당 클래스의 인스턴스가 다형성을 통해 다른 유형인 것처럼 가장할 때에도 호출되도록 교체합니다.위의 예를 참조하여 독자적인 클래스를 정의하고 toString() 함수를 덮어쓸 수 있습니다.이 함수는 개체에서 상속되므로 이 클래스의 인스턴스를 개체 유형 변수로 복사해도 계속 사용할 수 있습니다.일반적으로 클래스가 오브젝트인 척하고 있을 때 toString()을 호출하면 실제로 실행되는 toString 버전은 오브젝트 자체에 정의되어 있습니다.단, 함수는 오버라이드이기 때문에 클래스 인스턴스의 toString() 정의는 클래스 인스턴스의 실제 유형이 다형성 뒤에 숨겨져 있는 경우에도 사용됩니다.
오버로드란 이름이 같지만 파라미터가 다른 여러 메서드를 정의하는 작업입니다.이것은 덮어쓰기나 다형성과는 관련이 없다.
다형성은 요건에 따라 서로 다른 작업을 수행하는 둘 이상의 형태, 동일한 개체를 의미합니다.
다형성은 다음 두 가지 방법을 사용하여 달성할 수 있습니다.
- 메서드 덮어쓰기
- 메서드 오버로드
메서드 오버로드란 동일한 메서드 이름을 사용하여 같은 클래스에 여러 메서드를 쓰는 것을 의미하지만 전달 매개 변수가 다릅니다.
메서드 재정의는 다른 클래스에서 메서드 이름을 사용한다는 의미입니다. 즉, 부모 클래스 메서드가 자식 클래스에서 사용됨을 의미합니다.
Java에서는 슈퍼 클래스 참조 변수가 하위 클래스 개체를 유지할 수 있습니다.
다형성을 얻으려면 모든 개발자가 프로젝트에서 동일한 메서드 이름을 사용해야 합니다.
오버라이드 및 오버로드 모두 다형성을 실현하기 위해 사용됩니다.
하나 이상의 하위 클래스에서 재정의된 메서드를 클래스에 포함할 수 있습니다.메서드는 오브젝트를 인스턴스화하기 위해 사용된 클래스에 따라 다른 작업을 수행합니다.
abstract class Beverage {
boolean isAcceptableTemperature();
}
class Coffee extends Beverage {
boolean isAcceptableTemperature() {
return temperature > 70;
}
}
class Wine extends Beverage {
boolean isAcceptableTemperature() {
return temperature < 10;
}
}
또한 여러 인수 세트로 오버로드된 메서드를 사용할 수도 있습니다.메서드는 전달된 인수 유형에 따라 다양한 작업을 수행합니다.
class Server {
public void pour (Coffee liquid) {
new Cup().fillToTopWith(liquid);
}
public void pour (Wine liquid) {
new WineGlass().fillHalfwayWith(liquid);
}
public void pour (Lemonade liquid, boolean ice) {
Glass glass = new Glass();
if (ice) {
glass.fillToTopWith(new Ice());
}
glass.fillToTopWith(liquid);
}
}
다음으로 의사 C#/Java에서의 다형성의 예를 나타냅니다.
class Animal
{
abstract string MakeNoise ();
}
class Cat : Animal {
string MakeNoise () {
return "Meow";
}
}
class Dog : Animal {
string MakeNoise () {
return "Bark";
}
}
Main () {
Animal animal = Zoo.GetAnimal ();
Console.WriteLine (animal.MakeNoise ());
}
Main 함수는 동물의 유형을 인식하지 않으며 MakeNoise() 메서드의 특정 구현 동작에 따라 달라집니다.
편집: Brian이 펀치를 날 이긴 것 같아.우리가 같은 예를 사용했다는게 재밌다.그러나 위의 코드는 개념을 명확히 하는 데 도움이 될 것입니다.
오버로드가 해결책이 아니라는 것은 맞습니다.
둘 다 덮어쓰지는 않습니다.덮어쓰기란 다형성을 얻기 위한 수단이다.다형성은 물체의 종류에 따라 행동을 변화시키는 능력이다.이는 다형성을 나타내는 객체의 발신자가 객체의 특정 유형을 인식하지 못하는 경우에 가장 잘 나타납니다.
특히 과부하 또는 덮어쓰기라고 하는 것은 전체상을 나타내지 않습니다.다형성은 단순히 물체의 종류에 따라 행동을 전문화하는 능력이다.
같은 이름의 메서드가 다른 파라미터 유형을 제공할 수 있는 경우 오버로딩은 다형(파라메트릭 다형)의 한 형태라는 점에서 이 답변에 동의하지 않습니다.좋은 예로는 연산자 오버로드가 있습니다."+"를 정의하여 다른 유형의 매개 변수(예: 문자열 또는 int)를 받아들일 수 있습니다. 이러한 유형에 따라 "+"는 다르게 동작합니다.
다형성에는 상속 및 재정의 메서드도 포함되지만 기본 유형에서는 추상 또는 가상일 수 있습니다.상속 기반 다형성 측면에서 Java는 단일 클래스 상속만 지원하며, 기본 유형의 단일 체인으로 다형성 동작을 제한합니다.Java는 다형성 동작의 또 다른 형태인 여러 인터페이스의 구현을 지원합니다.
전형적인 예로는 개와 고양이는 동물이고 동물은 makeNoise라는 방법이 있습니다.나는 makeNoise라고 불리는 동물들의 배열을 통해 반복할 수 있고 그들이 각각의 구현을 할 것이라고 예상할 수 있다.
호출 코드는 그들이 어떤 동물인지 알 필요가 없다.
그것이 내가 생각하는 다형성이다.
다형성은 단순히 "다양한 형태"를 의미한다.
REQ는 하지 않습니다.UIRE 상속은 상속이 아닌 인터페이스 구현이 다형성 요구를 충족하기 때문에 실현됩니다.인터페이스 실장은 상속보다 다형성 요구를 충족시키는 것이 확실합니다.
예를 들어 날 수 있는 모든 것을 설명하는 슈퍼클래스를 만들 수 있습니까?아닌 것 같아요.당신은 비행을 설명하는 인터페이스를 만들고 그것을 그대로 두는 것이 가장 좋을 것이다.
따라서 인터페이스는 동작을 기술하고 메서드명은 동작을 기술하기 때문에 (프로그래머에게) 메서드 오버로드는 다형성의 덜한 형태로 간주해도 과언이 아닙니다.
다형성은 이미 이 글에 자세히 설명되어 있지만, 나는 왜 그 일부가 되었는지에 대해 더 강조하고 싶다.
왜 다형성이 OOP 언어에서 그렇게 중요한지.
상속/다형성이 있든 없든 TV용 심플한 어플리케이션을 만들어 봅시다.애플리케이션의 각 버전을 투고하면, 소규모 회고전을 실시합니다.
TV 회사의 소프트웨어 엔지니어로 볼륨, 휘도 및 컬러 컨트롤러의 사용자 명령 값을 늘리거나 낮추기 위해 소프트웨어를 작성해야 한다고 가정합니다.
이러한 각 기능에 대한 쓰기 클래스는 다음을 추가하여 시작합니다.
- set:- 컨트롤러의 값을 설정합니다.(컨트롤러 고유의 코드가 있는 경우)
- get:- 컨트롤러 값을 가져옵니다.(컨트롤러 고유의 코드가 있는 경우)
- adjust:- 입력을 검증하고 컨트롤러를 설정합니다.(일반적인 검증)컨트롤러에 의존하지 않음)
- 컨트롤러와의 사용자 입력 매핑: 사용자 입력을 가져오고 그에 따라 컨트롤러를 호출합니다.
응용 프로그램 버전 1
import java.util.Scanner;
class VolumeControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
/*
* There can be n number of controllers
* */
public class TvApplicationV1 {
public static void main(String[] args) {
VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
ColourControllerV1 colourControllerV1 = new ColourControllerV1();
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println("Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV1.adjust(5);
break;
}
case 2: {
volumeControllerV1.adjust(-5);
break;
}
case 3: {
brightnessControllerV1.adjust(5);
break;
}
case 4: {
brightnessControllerV1.adjust(-5);
break;
}
case 5: {
colourControllerV1.adjust(5);
break;
}
case 6: {
colourControllerV1.adjust(-5);
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
이것으로 델의 첫 번째 버전의 어플리케이션을 도입할 수 있게 되었습니다.지금까지의 작업을 분석할 시간입니다.
TV 어플리케이션 버전1의 문제
- 조정(int value) 코드가 세 클래스 모두에서 중복됩니다.코드 중복을 최소화해야 합니다.(그러나 코드 중복을 피하기 위해 공통 코드를 생각하지 않고 슈퍼 클래스로 이동했습니다.)
어플리케이션이 기대대로 동작하는 한, 당신은 그것을 감수하기로 결심합니다.
나중에 상사가 사용자에게 돌아와 기존 응용프로그램에 재설정 기능을 추가하도록 요청합니다.리셋 하면 3개의 컨트롤러가 모두 각각의 디폴트값으로 설정됩니다.
새로운 기능을 위한 새로운 클래스(Reset Function V2)를 작성하고 이 새로운 기능에 대한 사용자 입력 매핑코드를 매핑합니다.
응용 프로그램 버전 2
import java.util.Scanner;
class VolumeControllerV2 {
private int defaultValue = 25;
private int value;
int getDefaultValue() {
return defaultValue;
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV2 {
private int defaultValue = 50;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV2 {
private int defaultValue = 40;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ResetFunctionV2 {
private VolumeControllerV2 volumeControllerV2 ;
private BrightnessControllerV2 brightnessControllerV2;
private ColourControllerV2 colourControllerV2;
ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2) {
this.volumeControllerV2 = volumeControllerV2;
this.brightnessControllerV2 = brightnessControllerV2;
this.colourControllerV2 = colourControllerV2;
}
void onReset() {
volumeControllerV2.set(volumeControllerV2.getDefaultValue());
brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
colourControllerV2.set(colourControllerV2.getDefaultValue());
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV2 {
public static void main(String[] args) {
VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
ColourControllerV2 colourControllerV2 = new ColourControllerV2();
ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV2.adjust(5);
break;
}
case 2: {
volumeControllerV2.adjust(-5);
break;
}
case 3: {
brightnessControllerV2.adjust(5);
break;
}
case 4: {
brightnessControllerV2.adjust(-5);
break;
}
case 5: {
colourControllerV2.adjust(5);
break;
}
case 6: {
colourControllerV2.adjust(-5);
break;
}
case 7: {
resetFunctionV2.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
리셋 기능으로 어플리케이션이 준비되었습니다.하지만 이제서야 깨닫기 시작했구나
TV 어플리케이션 버전2의 문제
- 새로운 컨트롤러가 제품에 도입되면 Reset 기능 코드를 변경해야 합니다.
- 컨트롤러의 카운트가 매우 높아지면 컨트롤러의 참조를 유지하는 데 문제가 생깁니다.
- 재설정 피쳐 코드는 모든 컨트롤러 클래스의 코드와 긴밀하게 결합되어 있습니다(기본값을 가져오고 설정합니다).
- 기능 클래스 재설정(Reset Function V2)은 컨트롤러 클래스의 다른 메서드(조정)에 액세스할 수 있으며 이는 바람직하지 않습니다.
동시에, 각 컨트롤러가 기동시에, 인터넷을 개입시켜 회사의 호스트 드라이버 저장소에서 최신 버전의 드라이버를 확인할 필요가 있는 기능을 추가할 필요가 있다고 상사로부터 들었습니다.
이 새로운 기능이 리셋 기능과 비슷하다고 생각하기 시작합니다.어플리케이션을 재계수화하지 않으면 어플리케이션 문제(V2)가 증가합니다.
JAVA의 다형성 기능을 활용하여 새로운 추상 클래스(Controller V3)를 추가할 수 있도록 상속을 사용할 것을 생각하기 시작합니다.
- get 및 set 메서드의 시그니처를 선언합니다.
- 모든 컨트롤러 간에 이전에 복제된 조정 방식의 구현을 포함합니다.
- 폴리모피즘을 이용하여 리셋 기능을 쉽게 구현할 수 있도록 setDefault 메서드를 선언합니다.
이러한 개선으로 TV 애플리케이션 버전 3이 준비되었습니다.
응용 프로그램 버전 3
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
abstract class ControllerV3 {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3 {
private int defaultValue = 25;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
}
class BrightnessControllerV3 extends ControllerV3 {
private int defaultValue = 50;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
}
class ColourControllerV3 extends ControllerV3 {
private int defaultValue = 40;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
}
class ResetFunctionV3 {
private List<ControllerV3> controllers = null;
ResetFunctionV3(List<ControllerV3> controllers) {
this.controllers = controllers;
}
void onReset() {
for (ControllerV3 controllerV3 :this.controllers) {
controllerV3.setDefault();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV3 {
public static void main(String[] args) {
VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
ColourControllerV3 colourControllerV3 = new ColourControllerV3();
List<ControllerV3> controllerV3s = new ArrayList<>();
controllerV3s.add(volumeControllerV3);
controllerV3s.add(brightnessControllerV3);
controllerV3s.add(colourControllerV3);
ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV3.adjust(5);
break;
}
case 2: {
volumeControllerV3.adjust(-5);
break;
}
case 3: {
brightnessControllerV3.adjust(5);
break;
}
case 4: {
brightnessControllerV3.adjust(-5);
break;
}
case 5: {
colourControllerV3.adjust(5);
break;
}
case 6: {
colourControllerV3.adjust(-5);
break;
}
case 7: {
resetFunctionV3.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
V2의 문제 목록에 나열된 대부분의 문제는 해결되었지만,
TV 어플리케이션 버전3의 문제
- 기능 클래스 재설정(Reset Function V3)은 컨트롤러 클래스의 다른 메서드(조정)에 액세스할 수 있으며 이는 바람직하지 않습니다.
또, 이 문제를 해결하는 방법도 생각할 수 있습니다.기동시에 다른 기능(드라이버 업데이트)도 실장할 수 있게 되었습니다.수정하지 않으면 새 기능에도 복제됩니다.
그래서 추상 클래스에서 정의된 계약을 나누고 2개의 인터페이스를 작성합니다.
- 기능을 리셋합니다.
- 드라이버 업데이트
그리고 첫 번째 콘크리트 클래스에서 아래와 같이 실시하도록 합니다.
응용 프로그램 버전 4
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
interface OnReset {
void setDefault();
}
interface OnStart {
void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class VolumeControllerV4 extends ControllerV4 {
private int defaultValue = 25;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for VolumeController .... Done");
}
}
class BrightnessControllerV4 extends ControllerV4 {
private int defaultValue = 50;
private int value;
@Override
int get() {
return value;
}
@Override
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for BrightnessController .... Done");
}
}
class ColourControllerV4 extends ControllerV4 {
private int defaultValue = 40;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for ColourController .... Done");
}
}
class ResetFunctionV4 {
private List<OnReset> controllers = null;
ResetFunctionV4(List<OnReset> controllers) {
this.controllers = controllers;
}
void onReset() {
for (OnReset onreset :this.controllers) {
onreset.setDefault();
}
}
}
class InitializeDeviceV4 {
private List<OnStart> controllers = null;
InitializeDeviceV4(List<OnStart> controllers) {
this.controllers = controllers;
}
void initialize() {
for (OnStart onStart :this.controllers) {
onStart.checkForDriverUpdate();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV4 {
public static void main(String[] args) {
VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
ColourControllerV4 colourControllerV4 = new ColourControllerV4();
List<ControllerV4> controllerV4s = new ArrayList<>();
controllerV4s.add(brightnessControllerV4);
controllerV4s.add(volumeControllerV4);
controllerV4s.add(colourControllerV4);
List<OnStart> controllersToInitialize = new ArrayList<>();
controllersToInitialize.addAll(controllerV4s);
InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
initializeDeviceV4.initialize();
List<OnReset> controllersToReset = new ArrayList<>();
controllersToReset.addAll(controllerV4s);
ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV4.adjust(5);
break;
}
case 2: {
volumeControllerV4.adjust(-5);
break;
}
case 3: {
brightnessControllerV4.adjust(5);
break;
}
case 4: {
brightnessControllerV4.adjust(-5);
break;
}
case 5: {
colourControllerV4.adjust(5);
break;
}
case 6: {
colourControllerV4.adjust(-5);
break;
}
case 7: {
resetFunctionV4.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
이제 당신이 직면한 모든 문제가 해결되었고 당신은 상속과 다형성을 사용함으로써 당신이 할 수 있다는 것을 깨달았습니다.
- 애플리케이션의 다양한 부분을 느슨하게 결합해 둡니다(리셋 또는 드라이버 업데이트 기능 컴포넌트는 실제 컨트롤러 클래스(볼륨, 휘도 및 색상)를 인식할 필요가 없습니다.OnReset 또는 OnStart를 구현하는 클래스는 각각 리셋 또는 드라이버 업데이트 기능 컴포넌트로 허용됩니다).
- 애플리케이션 확장이 쉬워집니다.(컨트롤러를 새로 추가해도 리셋 또는 드라이버 업데이트 기능 컴포넌트에 영향을 주지 않으며, 새로운 컴포넌트를 쉽게 추가할 수 있게 되었습니다.)
- 추상화 층을 유지합니다.(이 시점에서 Reset 기능은 컨트롤러의 setDefault 메서드만 표시되며 Reset 기능은 컨트롤러의 checkForDriverUpdate 메서드만 표시됩니다.)
Hope, 이것은 도움이 된다:-)
다형성은 물체가 여러 형태로 나타나는 능력이다.여기에는 상속 및 가상 함수를 사용하여 상호 교환할 수 있는 개체 패밀리를 구축하는 작업이 포함됩니다.기본 클래스에는 구현되지 않았거나 애플리케이션이 지시하는 대로 기본 구현된 가상 기능의 프로토타입이 포함되어 있으며, 다양한 파생 클래스는 각각 다른 동작에 영향을 미치기 위해 이러한 프로토타입을 각각 다르게 구현합니다.
overload는 이름이 같지만 파라미터가 다른2개의 메서드를 정의하는 경우입니다.
오버라이드에서는 서브클래스에서 같은 이름의 함수를 통해 기본 클래스의 동작을 변경할 수 있습니다.
그래서 다형성은 오버라이드(override)와 관련이 있지만 실제로 과부하가 되지 않습니다.
하지만 누군가 "다형성이란 무엇인가?"라는 질문에 대해 "넘어감"이라는 간단한 답을 주었다면.자세한 설명을 부탁드립니다.
둘 다:
오버로드란 서로 다른 파라미터를 사용하는 동일한 함수 이름을 가진 경우입니다.
덮어쓰기란 자녀 클래스가 부모의 메서드를 부모의 메서드 중 하나로 대체하는 경우입니다(이 방법 자체는 다형성을 구성하지 않습니다).
다형성은 바인딩이 늦어지고 있습니다.예를 들어 기본 클래스(부모) 메서드가 호출되지만 실행 시 응용 프로그램이 실제 개체를 인식할 때까지 실행되지 않습니다. 메서드가 다른 자식 클래스일 수 있습니다.그 이유는 기본 클래스가 정의된 곳에서는 모든 자식 클래스를 사용할 수 있기 때문입니다.
Java에서는 컬렉션 라이브러리에서 다형을 많이 볼 수 있습니다.
int countStuff(List stuff) {
return stuff.size();
}
List는 기본 클래스입니다.Linked List, Vector, Array 또는 커스텀리스트 실장 중 어느 쪽을 카운트하고 있는지 컴파일러는 알 수 없습니다.List와 같이 동작하는 한:
List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);
과부하일 경우 다음과 같이 처리됩니다.
int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...
파라미터와 일치하는 올바른 버전의 count Stuff()가 컴파일러에 의해 선택됩니다.
다형성이란 무엇인가?
Java 튜토리얼에서
다형성의 사전적 정의는 생물이나 종이 많은 다른 형태나 단계를 가질 수 있는 생물학의 원리를 말한다.이 원리는 객체 지향 프로그래밍과 자바 언어 등 언어에도 적용될 수 있습니다.클래스의 하위 클래스는 고유한 동작을 정의하면서도 상위 클래스의 동일한 기능 중 일부를 공유할 수 있습니다.
예시와 정의를 고려하여 덮어쓰기를 허용해야 합니다.
두 번째 문의에 대해서:
구현되지 않은 메서드를 정의한 추상 기본 클래스가 있고 하위 클래스에서 해당 메서드를 정의한 경우 여전히 오버라이드입니까?
오버라이드라고 불러야 합니다.
이 예에서는 다양한 유형의 덮어쓰기를 이해할 수 있습니다.
- 기본 클래스는 구현을 제공하지 않으며 하위 클래스는 완전한 메서드를 재정의해야 합니다. - (추상)
- 기본 클래스는 기본 구현을 제공하며 하위 클래스는 동작을 변경할 수 있습니다.
- 는 기본 합니다.
super.methodName()
번째 - 기본 클래스는 알고리즘 구조(템플릿 메서드)를 정의하고 하위 클래스는 알고리즘의 일부를 덮어씁니다.
코드 스니펫:
import java.util.HashMap;
abstract class Game implements Runnable{
protected boolean runGame = true;
protected Player player1 = null;
protected Player player2 = null;
protected Player currentPlayer = null;
public Game(){
player1 = new Player("Player 1");
player2 = new Player("Player 2");
currentPlayer = player1;
initializeGame();
}
/* Type 1: Let subclass define own implementation. Base class defines abstract method to force
sub-classes to define implementation
*/
protected abstract void initializeGame();
/* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
protected void logTimeBetweenMoves(Player player){
System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
}
/* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
super.methodName() in first line of the child class method and specific implementation later */
protected void logGameStatistics(){
System.out.println("Base class: logGameStatistics:");
}
/* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
protected void runGame() throws Exception{
System.out.println("Base class: Defining the flow for Game:");
while ( runGame) {
/*
1. Set current player
2. Get Player Move
*/
validatePlayerMove(currentPlayer);
logTimeBetweenMoves(currentPlayer);
Thread.sleep(500);
setNextPlayer();
}
logGameStatistics();
}
/* sub-part of the template method, which define child class behaviour */
protected abstract void validatePlayerMove(Player p);
protected void setRunGame(boolean status){
this.runGame = status;
}
public void setCurrentPlayer(Player p){
this.currentPlayer = p;
}
public void setNextPlayer(){
if ( currentPlayer == player1) {
currentPlayer = player2;
}else{
currentPlayer = player1;
}
}
public void run(){
try{
runGame();
}catch(Exception err){
err.printStackTrace();
}
}
}
class Player{
String name;
Player(String name){
this.name = name;
}
public String getName(){
return name;
}
}
/* Concrete Game implementation */
class Chess extends Game{
public Chess(){
super();
}
public void initializeGame(){
System.out.println("Child class: Initialized Chess game");
}
protected void validatePlayerMove(Player p){
System.out.println("Child class: Validate Chess move:"+p.getName());
}
protected void logGameStatistics(){
super.logGameStatistics();
System.out.println("Child class: Add Chess specific logGameStatistics:");
}
}
class TicTacToe extends Game{
public TicTacToe(){
super();
}
public void initializeGame(){
System.out.println("Child class: Initialized TicTacToe game");
}
protected void validatePlayerMove(Player p){
System.out.println("Child class: Validate TicTacToe move:"+p.getName());
}
}
public class Polymorphism{
public static void main(String args[]){
try{
Game game = new Chess();
Thread t1 = new Thread(game);
t1.start();
Thread.sleep(1000);
game.setRunGame(false);
Thread.sleep(1000);
game = new TicTacToe();
Thread t2 = new Thread(game);
t2.start();
Thread.sleep(1000);
game.setRunGame(false);
}catch(Exception err){
err.printStackTrace();
}
}
}
출력:
Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
오버로드라는 용어는 같은 이름의 여러 버전이 있는 것을 의미합니다.일반적으로 파라미터 리스트가 다른 메서드입니다.
public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }
따라서 이러한 함수는 동일한 작업을 수행할 수 있지만 ID 또는 이름을 사용하여 호출할 수도 있습니다.상속, 추상 수업 등과는 관계가 없습니다.
오버라이드란 보통 질문에서 설명한 바와 같이 다형성을 말합니다.
오버라이드는 상위 수준 메서드(슈퍼 메서드)와 동일한 이름과 시그니처를 가진 메서드를 선언함으로써 상속된 메서드를 숨기는 것에 더 가깝습니다.즉, 호출되는 위치 수준 메서드를 선택하는 결정은 컴파일 시간이 아닌 런타임에 이루어집니다.이것은 interfac의 개념으로 이어집니다.를 참조해 주세요.
남자분들의 콘셉트가 좀 섞이는 것 같아요.다형성은 런타임에 다르게 동작하는 개체의 기능입니다.그러기 위해서는 다음 두 가지 요건이 필요합니다.
- 레이트 바인딩
- 상속.
오버로드란 사용하는 언어에 따라 덮어쓰기와는 다른 의미라고 말했습니다.예를 들어 Java에서는 오버라이드 대신 오버로드가 존재합니다.베이스 클래스에 시그니처가 다른 오버로드된 메서드는 서브 클래스에서 사용할 수 있습니다.그렇지 않으면 덮어쓰게 됩니다(오브젝트 외부에서 기본 클래스 메서드를 호출할 수 없습니다).
하지만 C++에서는 그렇지 않다.시그니처가 같은지 아닌지에 관계없이(다른 양, 다른 타입) 오버로드된 메서드도 마찬가지로 덮어씁니다.즉, 현재 base class의 메서드는 서브클래스 오브젝트 외부에서 호출될 때 서브클래스에서 사용할 수 없습니다.
따라서 Java 사용 오버로드에 대해 설명할 때 정답은 다음과 같습니다.다른 언어에서는 c++에서 발생하는 것과 다를 수 있습니다.
다형성은 그 의미에 관한 한 자바에서 오버라이드 될 가능성이 높다.
이 모든 것은 다른 상황에서 같은 오브젝트의 다른 동작에 관한 것입니다(프로그래밍 방법에서는...).다른 ACRUGES를 호출할 수 있습니다.)
아래의 예가 이해에 도움이 될 것이라고 생각합니다.PURE 자바 코드는 아니지만...
public void See(Friend)
{
System.out.println("Talk");
}
그러나 인수...를 변경하면 행동이 변경됩니다.
public void See(Enemy)
{
System.out.println("Run");
}
사용자(여기서 "개체")는 동일합니다...
수업 있다, 수업 있다, 수업 있다, 있다, 수업 있다, 있다.Animals
로서, 은 상상기기기기 called called called called called called called called called called called called called called called called called called called called called called called called called called called called called 라고 불리는 방법을 가지고 있다.movement()
동물이 움직이는 방식을 규정합니다.현재 우리는 다른 종류의 동물을 가지고 있고 그들은 또한 다르게 움직인다. 그들 중 몇몇은 다리가 2개인 동물이고, 다른 것들은 다리가 없는 동물들이다. 것을 movement()
하다 class를 정의해야 . 즉, class는 class를 더 많이 해야 합니다.Dogs
Cats
Fish
후, 베이스 「」로부터 가 있습니다. 그런 다음 기본 클래스에서 해당 클래스를 확장해야 합니다.Animals
을 무효로 하다movement()
각각의 동물을 기반으로 한 새로운 움직임 기능을 제공합니다. 이 경우에도 하실 수 있습니다.Interfaces
네, 네, 네.덮어쓰다개의 클래스에 할 수 .오버로드에서는 "같은 이름을 가진" 메서드를 여러 개 정의할 수 있지만 동일한 개체 또는 클래스에 서로 다른 매개 변수를 사용할 수 있습니다.
import java.io.IOException;
class Super {
protected Super getClassName(Super s) throws IOException {
System.out.println(this.getClass().getSimpleName() + " - I'm parent");
return null;
}
}
class SubOne extends Super {
@Override
protected Super getClassName(Super s) {
System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
return null;
}
}
class SubTwo extends Super {
@Override
protected Super getClassName(Super s) throws NullPointerException {
System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
return null;
}
}
class SubThree extends Super {
@Override
protected SubThree getClassName(Super s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
return null;
}
}
class SubFour extends Super {
@Override
protected Super getClassName(Super s) throws IOException {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
return null;
}
}
class SubFive extends Super {
@Override
public Super getClassName(Super s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
return null;
}
}
class SubSix extends Super {
public Super getClassName(Super s, String ol) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
return null;
}
}
class SubSeven extends Super {
public Super getClassName(SubSeven s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
return null;
}
}
public class Test{
public static void main(String[] args) throws Exception {
System.out.println("Overriding\n");
Super s1 = new SubOne(); s1.getClassName(null);
Super s2 = new SubTwo(); s2.getClassName(null);
Super s3 = new SubThree(); s3.getClassName(null);
Super s4 = new SubFour(); s4.getClassName(null);
Super s5 = new SubFive(); s5.getClassName(null);
System.out.println("Overloading\n");
SubSix s6 = new SubSix(); s6.getClassName(null, null);
s6 = new SubSix(); s6.getClassName(null);
SubSeven s7 = new SubSeven(); s7.getClassName(s7);
s7 = new SubSeven(); s7.getClassName(new Super());
}
}
폴리몰피즘은 단일 인터페이스를 사용하여 다른 오브젝트를 균일하게 취급하는 언어의 기능과 관련되어 있기 때문에 인터페이스(또는 베이스 클래스)는 폴리모픽이며 구현자는 (같은 메달의 두 면)을 오버라이드하는 오브젝트입니다.
어쨌든, 두 용어의 차이는 c++와 같은 다른 언어를 사용하여 더 잘 설명된다: c++의 다형성 객체는 기본 함수가 가상인 경우 자바 카운터로 동작하지만, 만약 방법이 가상이 아니라면 코드 점프는 정적으로 해결되고, 따라서 실행 시 체크되지 않은 참 유형은 다형성을 위한 능력을 포함한다.오브젝트 액세스에 사용되는 인터페이스에 따라 동작이 달라집니다.의사 코드로 예를 나타냅니다.
class animal {
public void makeRumor(){
print("thump");
}
}
class dog extends animal {
public void makeRumor(){
print("woff");
}
}
animal a = new dog();
dog b = new dog();
a.makeRumor() -> prints thump
b.makeRumor() -> prints woff
(makeRumor가 가상이 아닌 경우)
java는 실제로 이 수준의 다형성을 제공하지 않습니다(오브젝트 슬라이싱이라고도 함).
animal a = new dog(); dog b = new dog();
a.makeRumor() -> prints thump
b.makeRumor() -> prints woff
두 경우 모두 woff만 출력됩니다.a와 b가 클래스 개를 참조하고 있기 때문에
언급URL : https://stackoverflow.com/questions/154577/polymorphism-vs-overriding-vs-overloading
'sourcecode' 카테고리의 다른 글
C 문자열이 비어 있는지 확인하는 방법 (0) | 2022.08.16 |
---|---|
사용 정상 회의 버튼을 recaptcha 사용자 Vuejs의 반응에 따라. (0) | 2022.08.16 |
스낵바 Vuetify - 시간 초과 후 메서드 재정의 (0) | 2022.08.16 |
VueJS 애플리케이션을 통해 Google Analytics 4의 사용자 지정 차원을 전달하려면 어떻게 해야 합니까? (0) | 2022.08.16 |
Java에서 문자열을 UTF8 바이트 배열로 변환하는 방법 (0) | 2022.08.15 |