다형성 vs 재정의 vs 과부하
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
...
다형성 은 클래스 인스턴스가 마치 상속 트리에있는 다른 클래스의 인스턴스 인 것처럼 행동하는 능력입니다. 대부분의 경우 조상 클래스 중 하나입니다. 예를 들어 Java에서 모든 클래스는 Object에서 상속됩니다. 따라서 Object 유형의 변수를 작성하고 클래스의 인스턴스를 지정할 수 있습니다.
재정의 is a type of function which occurs in a class which inherits from another class. An override function "replaces" a function inherited from the base class, but does so in such a way that it is called even when an instance of its class is pretending to be a different type through polymorphism. Referring to the previous example, you could define your own class and override the toString() function. Because this function is inherited from Object, it will still be available if you copy an instance of this class into an Object-type variable. Normally, if you call toString() on your class while it is pretending to be an Object, the version of toString which will actually fire is the one defined on Object itself. However, because the function is an override, the definition of toString() from your class is used even when the class instance's true type is hidden behind polymorphism.
오버로드 는 이름은 같지만 매개 변수는 다른 여러 메소드를 정의하는 조치입니다. 재정의 또는 다형성과 관련이 없습니다.
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 () 메서드의 특정 구현 동작에 따라 다릅니다.
편집 : 브라이언이 나를 때리는 펀치처럼 보입니다. 우린 같은 예를 사용했습니다. 그러나 위의 코드는 개념을 명확히하는 데 도움이됩니다.
다형성이란 요구 사항에 따라 서로 다른 작업을 수행하는 하나 이상의 동일한 형태를 의미합니다.
다형성은 두 가지 방법으로 달성 할 수 있습니다.
- 메서드 재정의
- 메소드 오버로딩
메소드 오버로드 는 동일한 메소드 이름을 사용하여 동일한 클래스에 둘 이상의 메소드를 작성하는 것을 의미하지만 전달 매개 변수는 다릅니다.
메소드 재정의 는 다른 클래스에서 메소드 이름을 사용함을 의미하며, 이는 상위 클래스 메소드가 하위 클래스에서 사용됨을 의미합니다.
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);
}
}
과부하가 답이 아닌 것이 맞습니다.
어느 것도 무시하지 않습니다. 재정의는 다형성을 얻는 수단입니다. 다형성은 객체가 유형에 따라 동작을 변화시키는 능력입니다. 다형성을 나타내는 객체의 호출자가 객체의 특정 유형을 알지 못하는 경우에 가장 잘 설명됩니다.
특히 오버로드 또는 오버라이드는 전체 그림을 제공하지 않습니다. 다형성은 단순히 객체의 유형에 따라 동작을 특수화하는 능력입니다.
오버로드는 같은 이름의 메소드가 다르게 매개 변수 유형을 지정할 수있는 경우 다형성 (매개 변수 다형성)의 형태라는 점에서 일부 답변에 동의하지 않습니다. 좋은 예는 연산자 오버로드입니다. 문자열 또는 int와 같은 다른 유형의 매개 변수를 허용하도록 "+"를 정의 할 수 있으며 이러한 유형에 따라 "+"는 다르게 동작합니다.
다형성에는 상속 및 재정의 방법도 포함되지만 기본 유형에서는 추상적이거나 가상 일 수 있습니다. 상속 기반 다형성의 관점에서 Java는 단일 클래스 상속 만 지원하므로 단일 유형의 기본 유형 체인으로 다형성 동작을 제한합니다. Java는 또 다른 형태의 다형성 동작 인 다중 인터페이스의 구현을 지원합니다.
다형성은 단순히 "많은 형태"를 의미합니다.
상속이 아닌 인터페이스 구현으로 다형성 요구를 충족시키기 때문에 상속을 요구하지 않습니다. 논란의 여지가 있지만 인터페이스 구현은 상속보다 "더 나은"다형성 요구를 충족시킵니다.
예를 들어, 날 수있는 모든 것을 설명하는 수퍼 클래스를 만드시겠습니까? 나는 생각하지 않아야한다. 비행을 설명하는 인터페이스를 작성하고 그대로 두는 것이 가장 좋습니다.
따라서 인터페이스는 동작을 설명하고 메소드 이름은 동작을 (프로그래머에게) 설명하므로 메소드 오버로드를 더 적은 형태의 다형성으로 간주하기에는 무리가 없습니다.
고전적인 예, 개와 고양이는 동물이며, 동물은 makeNoise 방법을 가지고 있습니다. 나는 그들에게 makeNoise를 호출하는 일련의 동물을 반복하고 그들이 각각의 구현을 할 것으로 기대합니다.
호출 코드는 그들이 어떤 특정 동물인지 알 필요가 없습니다.
그것이 내가 다형성이라고 생각하는 것입니다.
다형성은 객체가 여러 형태로 나타나는 능력입니다. 여기에는 상속 및 가상 함수를 사용하여 상호 교환 할 수있는 개체군을 구축하는 것이 포함됩니다. 기본 클래스에는 응용 프로그램이 지시 한대로 구현되지 않았거나 기본 구현으로 구현 된 가상 함수의 프로토 타입이 포함되어 있으며 다양한 파생 클래스는 각각 다른 동작에 영향을주기 위해 다르게 구현합니다.
둘 다 :
오버로드는 다른 매개 변수를 사용하는 동일한 기능 이름을 갖는 경우입니다.
재정의는 자식 클래스가 부모의 메서드를 자체 메서드 중 하나로 대체 할 때입니다 (자체적으로 다형성을 구성하지 않음).
다형성은 늦은 바인딩입니다. 예를 들어 기본 클래스 (부모) 메서드가 호출되고 있지만 런타임에 응용 프로그램에서 실제 개체가 무엇인지 알 때까지는 그렇지 않습니다. 메서드가 다른 자식 클래스 일 수 있습니다. 기본 클래스가 정의 된 모든 하위 클래스를 사용할 수 있기 때문입니다.
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 ()가 매개 변수와 일치하도록 컴파일러에 의해 선택됩니다.
오버로딩이라는 용어는 같은 이름을 가진 여러 버전의 무언가를 가지며 일반적으로 매개 변수 목록이 다른 메소드를 말합니다
public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }
따라서 이러한 함수는 동일한 기능을 수행 할 수 있지만 ID 또는 이름으로 호출 할 수 있습니다. 상속, 추상 클래스 등과는 아무런 관련이 없습니다.
재정의는 일반적으로 질문에 설명 된 것처럼 다형성을 나타냅니다.
오버로드는 이름은 같지만 매개 변수가 다른 두 개의 메소드를 정의 할 때입니다.
재정의는 하위 클래스에서 이름이 같은 함수를 통해 기본 클래스의 동작을 변경하는 곳입니다.
따라서 다형성은 재정의와 관련이 있지만 실제로 과부하는 아닙니다.
그러나 누군가 "다형성이란 무엇입니까?" 자세한 설명을 부탁 드리겠습니다.
재정의는 상위 수준 메서드 (슈퍼 메서드)와 이름과 서명이 같은 메서드를 선언하여 상속 된 메서드를 숨기는 것과 비슷합니다. 이렇게하면 클래스에 다형성 동작이 추가됩니다. 다시 말해서 호출 할 수준의 메소드를 선택하기로 한 결정은 컴파일 타임이 아닌 런타임에 이루어집니다. 이것은 인터페이스와 구현의 개념으로 이어진다.
다형성이란 무엇입니까?
자바 튜토리얼에서
다형성의 사전 정의는 유기체 또는 종이 많은 다른 형태 또는 단계를 가질 수있는 생물학의 원리를 의미합니다. 이 원칙은 객체 지향 프로그래밍 및 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 ++에서와 같이 다를 수 있습니다.
다형성에 대해서는 이미이 글에서 자세하게 설명하고 있지만 그 이유에 대해 더 강조하고 싶습니다.
모든 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의 문제
- 3 개의 클래스 모두에서 Adjust (int value) 코드가 중복됩니다. 코드 이중성을 최소화하고 싶습니다. (그러나 중복 코드를 피하기 위해 공통 코드를 생각하지 않고 슈퍼 클래스로 옮기지 않았습니다)
응용 프로그램이 예상대로 작동하는 한 계속 사용하기로 결정했습니다.
때때로, 당신의 보스가 당신에게 돌아와서 기존 응용 프로그램에 재설정 기능을 추가하도록 요청합니다. 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의 문제
- 새 컨트롤러가 제품에 도입 된 경우 재설정 기능 코드를 변경해야합니다.
- 컨트롤러 수가 너무 많으면 컨트롤러 참조를 보유하는 데 문제가있을 수 있습니다.
- 리셋 기능 코드는 모든 컨트롤러 클래스의 코드와 밀접하게 연결되어 있습니다 (기본값 설정 및 가져 오기).
- 기능 클래스 재설정 (ResetFunctionV2)은 바람직하지 않은 Controller 클래스의 다른 방법 (조정)에 액세스 할 수 있습니다.
동시에, 보스로부터 귀하는 각 컨트롤러가 시작시 인터넷을 통해 회사의 호스트 드라이버 저장소에서 최신 버전의 드라이버를 확인해야하는 기능을 추가해야 할 수도 있다고 들었습니다.
이제 추가 할이 새로운 기능이 재설정 기능과 비슷하며 응용 프로그램을 리팩터링하지 않으면 V2 (응용 프로그램 문제)가 곱해질 것이라고 생각하기 시작합니다.
JAVA의 다형성 (polymorphic) 기능을 활용할 수 있도록 상속 사용을 고려하고 새로운 추상 클래스 (ControllerV3)를
- get 및 set 메소드의 서명을 선언하십시오.
- 모든 컨트롤러에서 이전에 복제 된 adjust 메소드 구현을 포함합니다.
- 다형성을 활용하여 재설정 기능을 쉽게 구현할 수 있도록 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의 문제
- 기능 클래스 재설정 (ResetFunctionV3)은 바람직하지 않은 Controller 클래스의 다른 방법 (조정)에 액세스 할 수 있습니다.
다시 말하지만, 구현할 다른 기능 (시작시 드라이버 업데이트)이 있으므로이 문제를 해결하려고합니다. 수정하지 않으면 새로운 기능으로 복제됩니다.
따라서 추상 클래스에 정의 된 계약을 나누고 두 가지 인터페이스를 작성하십시오.
- 기능을 재설정하십시오.
- 드라이버 업데이트.
그리고 첫 번째 구체적인 수업에 아래와 같이 구현하십시오.
응용 프로그램 버전 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를 구현하는 모든 클래스는 재설정 또는 드라이버 업데이트 기능을 사용할 수 있습니다 구성 요소).
- 응용 프로그램 향상이 쉬워집니다 (컨트롤러의 새로운 추가는 재설정 또는 드라이버 업데이트 기능 구성 요소에 영향을 미치지 않으며 이제 새로운 구성 요소를 추가하는 것이 매우 쉽습니다)
- 추상화 계층 유지 (이제 재설정 기능은 컨트롤러의 setDefault 메소드 만 볼 수 있고 재설정 기능은 컨트롤러의 checkForDriverUpdate 메소드 만 볼 수 있음)
도움이 되었기를 바랍니다 :-)
다형성은 그 의미 가 관련 이있는 한 더 가능성이 높습니다 ... 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());
}
}
참고 URL : https://stackoverflow.com/questions/154577/polymorphism-vs-overriding-vs-overloading
'development' 카테고리의 다른 글
| 휘발성 키워드를 사용하는 이유는 무엇입니까? (0) | 2020.03.03 |
|---|---|
| Swift를 사용하여 앱 버전 및 빌드 번호를 어떻게 얻습니까? (0) | 2020.03.03 |
| PHP에서 cURL을 사용하여 Tor 숨김 서비스에 연결하려면 어떻게해야합니까? (0) | 2020.03.03 |
| OnBeforeUnload 대화 상자를 재정의하고 내 대화 상자로 바꾸려면 어떻게해야합니까? (0) | 2020.03.03 |
| NSInteger와 int를 사용하는 경우 (0) | 2020.03.03 |