Java의 관점에서 누군가가 물을 때 :
다형성이란 무엇입니까?
겠습니까 과부하 또는 재정의 허용 해답이 될?
나는 그것보다 조금 더 있다고 생각합니다.
구현하지 않고 메소드를 정의한 추상 기본 클래스가 있고 서브 클래스에서 해당 메소드를 정의한 경우 여전히 대체입니까?
오버로드 가 정답이 아니라고 생각 합니다.
Java의 관점에서 누군가가 물을 때 :
다형성이란 무엇입니까?
겠습니까 과부하 또는 재정의 허용 해답이 될?
나는 그것보다 조금 더 있다고 생각합니다.
구현하지 않고 메소드를 정의한 추상 기본 클래스가 있고 서브 클래스에서 해당 메소드를 정의한 경우 여전히 대체입니까?
오버로드 가 정답이 아니라고 생각 합니다.
답변:
다형성을 표현하는 가장 명확한 방법은 추상 기본 클래스 (또는 인터페이스)를 사용하는 것입니다.
public abstract class Human{
...
public abstract void goPee();
}
이 클래스는 goPee()
메소드가 인간에게 정의 할 수 없기 때문에 추상적 입니다. 서브 클래스 Male 및 Female에 대해서만 정의 할 수 있습니다. 또한 인간은 추상적 개념입니다. 남성도 여성도 아닌 인간을 만들 수는 없습니다. 둘 중 하나 여야합니다.
따라서 추상 클래스를 사용하여 구현을 연기합니다.
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
...
goPee
중력장을 입력으로 사용하지 않습니다. 전역 상태에 대한 이러한 의존성으로 인해 단위 테스트가 CatheterizedIntersexAstronaut
어려워지고 서브 클래 싱이 특성의 구성을위한 최선의 방법은 아닐 수도 있습니다.
다형성 (polymorphism) 은 클래스 인스턴스가 마치 상속 트리에있는 다른 클래스의 인스턴스 인 것처럼 행동하는 능력입니다. 대부분의 경우 조상 클래스 중 하나입니다. 예를 들어 Java에서 모든 클래스는 Object에서 상속됩니다. 따라서 Object 유형의 변수를 작성하고 클래스의 인스턴스를 지정할 수 있습니다.
재정의다른 클래스에서 상속되는 클래스에서 발생하는 함수 유형입니다. 재정의 함수는 기본 클래스에서 상속 된 함수를 "대체"하지만 클래스의 인스턴스가 다형성을 통해 다른 유형 인 척하는 경우에도 호출되는 방식으로 호출됩니다. 이전 예제를 참조하면 자신의 클래스를 정의하고 toString () 함수를 재정의 할 수 있습니다. 이 함수는 Object에서 상속되므로이 클래스의 인스턴스를 Object-type 변수에 복사하면 계속 사용할 수 있습니다. 일반적으로 클래스가 Object 인 것처럼 클래스에서 toString ()을 호출하면 실제로 실행되는 toString 버전은 Object 자체에 정의 된 버전입니다. 그러나 함수가 재정의이므로 클래스 인스턴스의 toString () 정의는 클래스 인스턴스가
오버로드 는 이름은 같지만 매개 변수가 다른 여러 메소드를 정의하는 조치입니다. 재정의 또는 다형성과 관련이 없습니다.
Ad hoc polymorphism
당신이 당신의 설명 무엇 오버로딩의 섹션 입니다 다형성의 경우.
다형성이란 요구 사항에 따라 다른 작업을 수행하는 하나 이상의 동일한 형태를 의미합니다.
다형성은 두 가지 방법으로 달성 할 수 있습니다.
메소드 오버로드 는 동일한 메소드 이름을 사용하여 동일한 클래스에 둘 이상의 메소드를 작성하는 것을 의미하지만 전달 매개 변수는 다릅니다.
메서드 재정의 는 다른 클래스에서 메서드 이름을 사용한다는 것을 의미합니다. 즉, 부모 클래스 메서드는 자식 클래스에서 사용됩니다.
Java에서 다형성을 달성하기 위해 수퍼 클래스 참조 변수는 서브 클래스 오브젝트를 보유 할 수 있습니다.
다형성을 달성하려면 모든 개발자가 프로젝트에서 동일한 메소드 이름을 사용해야합니다.
pseudo-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 () 메서드의 특정 구현 동작에 따라 다릅니다.
편집 : 브라이언이 나를 때리는 펀치처럼 보입니다. 우린 같은 예를 사용했습니다. 그러나 위의 코드는 개념을 명확히하는 데 도움이됩니다.
재정의와 과부하 모두 다형성을 달성하는 데 사용됩니다.
하나 이상의 서브 클래스에서 재정의 되는 클래스에 메소드가있을 수 있습니다 . 이 메소드는 객체를 인스턴스화하는 데 사용 된 클래스에 따라 다른 작업을 수행합니다.
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);
}
}
과부하가 답이 아닌 것이 맞습니다.
어느 것도 무시하지 않습니다. 재정의는 다형성을 얻는 수단입니다. 다형성은 객체가 유형에 따라 동작을 변화시키는 능력입니다. 다형성을 나타내는 객체의 호출자가 객체의 특정 유형을 알지 못하는 경우에 가장 잘 설명됩니다.
특히 오버로드 또는 오버라이드는 전체 그림을 제공하지 않습니다. 다형성은 단순히 객체의 유형에 따라 동작을 특수화하는 능력입니다.
오버로드는 같은 이름의 메소드가 다르게 매개 변수 유형을 지정할 수있는 경우 다형성 (매개 변수 다형성)의 형태라는 점에서 일부 답변에 동의하지 않습니다. 좋은 예는 연산자 오버로드입니다. 문자열 또는 int와 같은 다른 유형의 매개 변수를 허용하도록 "+"를 정의 할 수 있으며 이러한 유형에 따라 "+"는 다르게 동작합니다.
다형성에는 상속 및 재정의 방법도 포함되지만 기본 유형에서는 추상적이거나 가상 일 수 있습니다. 상속 기반 다형성 측면에서 Java는 단일 클래스 상속 만 지원하여 단일 유형의 기본 유형 체인의 다형성 동작으로 제한합니다. Java는 또 다른 형태의 다형성 동작 인 다중 인터페이스의 구현을 지원합니다.
다형성은 단순히 "많은 형태"를 의미합니다.
상속이 아닌 인터페이스 구현으로 다목적 요구를 충족시키기 때문에 상속을 요구하지 않습니다. 논란의 여지가 있지만 인터페이스 구현은 상속보다 "더 나은"다형성 요구를 충족시킵니다.
예를 들어, 날 수있는 모든 것을 설명하는 수퍼 클래스를 만드시겠습니까? 나는 생각하지 않아야한다. 비행을 설명하는 인터페이스를 작성하고 그대로 두는 것이 가장 좋습니다.
따라서 인터페이스는 동작을 설명하고 메서드 이름은 동작을 (프로그래머에게) 설명하므로 메서드 오버로드를 더 적은 형태의 다형성으로 간주하기에는 무리가 없습니다.
둘 다 :
오버로드는 다른 매개 변수를 사용하는 동일한 기능 이름을 갖는 경우입니다.
재정의는 자식 클래스가 부모의 메서드를 자체 메서드 중 하나로 대체 할 때입니다 (자체적으로 다형성을 구성하지 않음).
다형성은 늦은 바인딩입니다. 예를 들어 기본 클래스 (부모) 메서드가 호출되고 있지만 런타임에 응용 프로그램에서 실제 개체가 무엇인지 알 때까지는 그렇지 않습니다. 메서드가 다른 자식 클래스 일 수 있습니다. 기본 클래스가 정의 된 모든 하위 클래스를 사용할 수 있기 때문입니다.
Java에서는 콜렉션 라이브러리에서 다형성을 많이 볼 수 있습니다.
int countStuff(List stuff) {
return stuff.size();
}
List는 기본 클래스이며, List처럼 작동하는 한 연결된 목록, 벡터, 배열 또는 사용자 정의 목록 구현을 계산하는 경우 컴파일러는 실마리가 없습니다.
List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);
과부하가 발생하면 다음을 수행하십시오.
int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...
그리고 올바른 버전의 countStuff ()가 매개 변수와 일치하도록 컴파일러에서 선택됩니다.
다형성에 대해서는 이미이 글에서 자세하게 설명하고 있지만 그 이유에 대해 더 강조하고 싶습니다.
모든 OOP 언어에서 다형성이 중요한 이유
상속 / 다형성이 있거나없는 TV를위한 간단한 응용 프로그램을 만들어 봅시다. 응용 프로그램의 각 버전을 게시하면 소급 적용됩니다.
TV 회사의 소프트웨어 엔지니어이고 볼륨, 밝기 및 색상 컨트롤러 용 소프트웨어를 작성하여 사용자 명령에서 값을 늘리거나 줄이라고 가정합니다.
다음을 추가하여 이러한 각 기능에 대한 클래스 작성으로 시작하십시오.
응용 프로그램 버전 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의 문제
응용 프로그램이 예상대로 작동하는 한 계속 사용하기로 결정했습니다.
때때로, 당신의 보스가 당신에게 돌아와서 기존 응용 프로그램에 재설정 기능을 추가하도록 요청합니다. Reset은 3 개의 3 개의 컨트롤러를 각각의 기본값으로 설정합니다.
새 기능에 대한 새 클래스 (ResetFunctionV2)를 작성하기 시작하고이 새 기능에 대한 사용자 입력 맵핑 코드를 맵핑하십시오.
응용 프로그램 버전 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의 문제
동시에, 보스로부터 귀하는 각 컨트롤러가 시작시 인터넷을 통해 회사의 호스트 드라이버 저장소에서 최신 버전의 드라이버를 확인해야하는 기능을 추가해야 할 수도 있다고 들었습니다.
이제 추가 할이 새로운 기능이 재설정 기능과 유사하며 응용 프로그램을 리팩터링하지 않으면 V2 (응용 프로그램 문제)가 곱해질 것이라고 생각하기 시작합니다.
JAVA의 다형성 (polymorphic) 기능을 활용할 수 있도록 상속 사용을 고려하고 새로운 추상 클래스 (ControllerV3)를 추가합니다.
이러한 개선 사항을 통해 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의 문제
다시 말하지만, 구현할 다른 기능 (시작시 드라이버 업데이트)이 있으므로이 문제를 해결하려고합니다. 수정하지 않으면 새로운 기능으로 복제됩니다.
따라서 추상 클래스에 정의 된 계약을 나누고 두 가지 인터페이스를 작성하십시오.
그리고 첫 번째 구체적인 수업에 아래와 같이 구현하십시오.
응용 프로그램 버전 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;
}
}
}
}
이제 당신이 직면 한 모든 문제가 해결되었으며 상속과 다형성을 사용하면
도움이 되었기를 바랍니다 :-)
다형성이란 무엇입니까?
자바 튜토리얼에서
다형성의 사전 정의는 유기체 또는 종이 다양한 형태 또는 단계를 가질 수있는 생물학의 원리를 말합니다. 이 원칙은 객체 지향 프로그래밍 및 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:
나는 너희들이 개념을 섞고 있다고 생각한다. 다형성 은 객체가 런타임에 다르게 동작하는 능력입니다. 이를 위해서는 두 가지 필수 조건이 필요합니다.
말해 두 겠는데 그 과부하 수단을에 다른 것을 무시 당신이 사용하는 언어에 따라. 예를 들어 Java에서는 재정의가 아니라 과부하 가 존재합니다 . 서브 클래스에서 기본 클래스와 다른 서명을 가진 오버로드 된 메소드를 사용할 수 있습니다. 그렇지 않으면 그것들이 무시 될 것입니다 (제발, 객체 외부에서 기본 클래스 메소드를 호출 할 수있는 방법이 없다는 것을 의미합니다).
그러나 C ++에서는 그렇지 않습니다. 상관 과부하 에있어서, 상기 서명이 아니라 동일한 여부 (diffrrent 양은 다른 타입) 독립적 여부 재정의가 . 즉, 기본 클래스의 메소드는 서브 클래스 객체 외부에서 호출 될 때 더 이상 서브 클래스에서 더 이상 사용할 수 없습니다.
따라서 Java 사용 오버로딩 에 대해 이야기 할 때 답이됩니다 . 다른 언어에서는 C ++에서와 같이 다를 수 있습니다.
다형성은 그것이 의미하는 한 더 가능성이 높습니다 가 관련 ... Java에서 덮어 쓰기
각기 다른 상황에서 SAME 객체의 다른 행동에 관한 것입니다 (프로그래밍 방식에서 ... 다른 인수를 호출 할 수 있습니다)
아래 예제는 이해하는 데 도움이 될 것이라고 생각합니다 ... PURE Java 코드는 아니지만 ...
public void See(Friend)
{
System.out.println("Talk");
}
그러나 우리가 인수를 바꾸면 ... 행동이 바뀔 것입니다 ...
public void See(Enemy)
{
System.out.println("Run");
}
Person (여기서는 "Object")은 동일합니다 ...
다형성은 객체의 여러 구현이거나 여러 형태의 객체를 말할 수 있습니다. 클래스 Animals
를 추상 기본 클래스로 사용하고 movement()
동물이 움직이는 방식을 정의 하는 메소드 가 있습니다. 실제로 우리는 서로 다른 종류의 동물을 가지고 있으며 그것들은 다르게 움직입니다. 그들 중 일부는 2 개의 다리로, 다른 것은 4 개, 그리고 다리가없는 일부 등입니다. movement()
지구상의 각 동물마다 다른 것을 정의하려면 다형성을 적용해야합니다. 그러나 더 많은 클래스, 즉 클래스 Dogs
Cats
Fish
등 을 정의해야합니다 . 그런 다음 기본 클래스에서 해당 클래스를 확장 Animals
하고 해당 메소드를 대체해야합니다.movement()
가지고있는 각 동물을 기반으로하는 새로운 이동 기능으로 를 해야합니다. 당신은 또한 사용할 수 있습니다Interfaces
그것을 달성하기 위해. 여기의 키워드는 재정의 중이며, 과부하가 다를 수 있으며 다형성으로 간주되지 않습니다. 오버로딩을 사용하면 "같은 이름으로"여러 객체를 정의 할 수 있지만 동일한 객체 나 클래스에서 다른 매개 변수를 사용하면됩니다.
다형성은 단일 인터페이스를 사용하여 언어가 다른 객체를 균일하게 처리하는 능력과 관련이 있습니다. 따라서 재정의와 관련이 있으므로 인터페이스 (또는 기본 클래스)는 다형성이며 구현자는 재정의하는 객체입니다 (동일한 메달의두면).
어쨌든 두 용어의 차이점은 c ++과 같은 다른 언어를 사용하여 더 잘 설명됩니다 .c ++의 다형성 객체는 기본 함수가 가상 인 경우 Java 대응 기능으로 작동하지만 메서드가 가상이 아닌 경우 코드 점프는 정적으로 해결됩니다 . 런타임에 확인되지 않은 트루 타입이므로 다형성에는 객체에 액세스하는 데 사용되는 인터페이스에 따라 객체가 다르게 동작하는 기능이 포함됩니다. 의사 코드로 예를 들어 보겠습니다.
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는 이러한 수준의 다형성 (객체 슬라이싱이라고도 함)을 제공하지 않습니다.
동물 a = 새 개 (); 개 b = 새 개 ();
a.makeRumor() -> prints thump
b.makeRumor() -> prints woff
두 경우 모두 woff 만 인쇄합니다. a와 b는 클래스 도그를 참조하기 때문에
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());
}
}