문제

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에서 모든 클래스는 객체에서 상속됩니다. 따라서 유형 객체의 변수를 생성하고 모든 클래스의 인스턴스에 할당 할 수 있습니다.

an 우세하다 다른 클래스에서 상속되는 클래스에서 발생하는 함수 유형입니다. 재정의 함수는 기본 클래스에서 상속 된 함수를 "대체"하지만, 클래스의 인스턴스가 다형성을 통해 다른 유형 인 척하는 경우에도 호출되는 방식으로 그렇게합니다. 이전 예를 참조하면 자신의 클래스를 정의하고 toString () 함수를 무시할 수 있습니다. 이 함수는 객체에서 상속 되므로이 클래스의 인스턴스를 객체 유형 변수로 복사하면 여전히 사용할 수 있습니다. 일반적으로, 수업에서 Tostring ()을 호출하면 객체 인 척하는 동안 실제로 발사되는 Tostring의 버전은 객체 자체에 정의 된 것입니다. 그러나 함수는 재정의이기 때문에 클래스 인스턴스의 실제 유형이 다형성 뒤에 숨겨져있는 경우에도 클래스의 Tostring ()의 정의가 사용됩니다.

과부하 동일한 이름으로 여러 메소드를 정의하지만 매개 변수가 다른 동작입니다. 그것은 무시하거나 다형성과 관련이 없습니다.

다음은 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 ());
}

주요 기능은 동물의 유형을 알지 못하고 Makenoise () 메소드의 특정 구현 동작에 따라 다릅니다.

편집 : Brian이 나를 펀치로 이겼던 것 같습니다. 우리는 같은 예를 사용했습니다. 그러나 위의 코드는 개념을 명확히하는 데 도움이 될 것입니다.

다형성은 요구 사항에 따라 다른 작업을 수행하는 동일한 객체 이상의 형태를 의미합니다.

다형성은 두 가지 방법을 사용하여 달성 할 수 있습니다.

  1. 메소드 오버링
  2. 메소드 과부하

메소드 과부하 동일한 메소드 이름을 사용하여 동일한 클래스에서 두 가지 이상의 메소드를 작성하지만 전달 매개 변수는 다릅니다.

메소드 오버링 다른 클래스에서 메소드 이름을 사용한다는 것을 의미합니다. 즉, 부모 클래스 메소드가 아동 클래스에서 사용되는 것을 의미합니다.

다형성을 달성하기 위해 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는 또 다른 형태의 다형성 거동 인 여러 인터페이스의 구현을 지원합니다.

다형성은 단순히 "많은 형태"를 의미합니다.

상속이 아닌 인터페이스 구현이 다형성 요구에 부합하는 인터페이스 구현이 달성하기 위해 상속을 요구하지 않습니다. 아마도 인터페이스 구현은 상속보다 "더 나은"다형성 요구에 부합합니다.

예를 들어, 날 수있는 모든 것을 설명하기 위해 슈퍼 클래스를 만들 수 있습니까? 나는 생각하지 않아야한다. 비행을 설명하고 그대로 두는 인터페이스를 만드는 데 가장 적합한 서비스를받을 수 있습니다.

따라서 인터페이스가 동작을 설명하고 메소드 이름은 행동 (프로그래머에게)을 설명하기 때문에 방법 과부하가 다형성의 형태로 고려하기에는 너무 멀지 않습니다.

고전적인 예, 개와 고양이는 동물이며 동물은 방법을 kakeoise합니다. 나는 그들에게 Makenoise를 부르는 다양한 동물을 반복 할 수 있으며 각각의 구현을 기대할 수 있습니다.

호출 코드는 그들이 어떤 특정 동물인지 알 필요가 없습니다.

그것이 내가 다형성으로 생각하는 것입니다.

다형성은 물체가 여러 형태로 나타나는 능력입니다. 여기에는 상속 및 가상 기능을 사용하여 교환 할 수있는 물체 제품군을 구축하는 것이 포함됩니다. 기본 클래스에는 애플리케이션이 지시되는대로 구현되지 않았거나 기본 구현이 포함되어 있거나 다양한 파생 클래스가 서로 다른 동작에 영향을 미치기 위해 다르게 구현합니다.

Neither:

Overloading is when you have the same function name that takes different parameters.

Overriding is when a child class replaces a parent's method with one of its own (this in iteself does not constitute polymorphism).

Polymorphism is late binding, e.g. the base class (parent) methods are being called but not until runtime does the application know what the actual object is - it may be a child class whose methods are different. This is because any child class can be used where a base class is defined.

In Java you see polymorphism a lot with the collections library:

int countStuff(List stuff) {
  return stuff.size();
}

List is the base class, the compiler has no clue if you're counting a linked list, vector, array, or a custom list implementation, as long as it acts like a List:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

If you were overloading you'd have:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

and the correct version of countStuff() would be picked by the compiler to match the parameters.

The term overloading refers to having multiple versions of something with the same name, usually methods with different parameter lists

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

So these functions might do the same thing but you have the option to call it with an ID, or a name. Has nothing to do with inheritance, abstract classes, etc.

Overriding usually refers to polymorphism, as you described in your question

overloading is when you define 2 methods with the same name but different parameters

overriding is where you change the behavior of the base class via a function with the same name in a subclass.

So Polymorphism is related to overriding but not really overloading.

However if someone gave me a simple answer of "overriding" for the question "What is polymorphism?" I would ask for further explanation.

overriding is more like hiding an inherited method by declaring a method with the same name and signature as the upper level method (super method), this adds a polymorphic behaviour to the class . in other words the decision to choose wich level method to be called will be made at run time not on compile time . this leads to the concept of interface and implementation .

what is polymorphism?

From java tutorial

The dictionary definition of polymorphism refers to a principle in biology in which an organism or species can have many different forms or stages. This principle can also be applied to object-oriented programming and languages like the Java language. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.

By considering the examples and definition, overriding should be accepted answer.

Regarding your second query:

IF you had a abstract base class that defined a method with no implementation, and you defined that method in the sub class, is that still overridding?

It should be called overriding.

Have a look at this example to understand different types of overriding.

  1. Base class provides no implementation and sub-class has to override complete method - (abstract)
  2. Base class provides default implementation and sub-class can change the behaviour
  3. Sub-class adds extension to base class implementation by calling super.methodName() as first statement
  4. Base class defines structure of the algorithm (Template method) and sub-class will override a part of algorithm

code snippet:

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();
        }       
    }
}

output:

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:

I think guys your are mixing concepts. Polymorphism is the ability of an object to behave differently at run time. For achieving this, you need two requisites:

  1. Late Binding
  2. Inheritance.

Having said that overloading means something different to overriding depending on the language you are using. For example in Java does not exist overriding but overloading. Overloaded methods with different signature to its base class are available in the subclass. Otherwise they would be overridden (please, see that I mean now the fact of there is no way to call your base class method from outside the object).

However in C++ that is not so. Any overloaded method, independently whether the signature is the same or not (diffrrent amount, different type) is as well overridden. That is to day, the base class' method is no longer available in the subclass when being called from outside the subclass object, obviously.

So the answer is when talking about Java use overloading. In any other language may be different as it happens in c++

Although, Polymorphism is already explained in great details in this post but I would like put more emphasis on why part of it.

Why Polymorphism is so important in any OOP language.

Let’s try to build a simple application for a TV with and without Inheritance/Polymorphism. Post each version of the application, we do a small retrospective.

Supposing, you are a software engineer at a TV company and you are asked to write software for Volume, Brightness and Colour controllers to increase and decrease their values on user command.

You start with writing classes for each of these features by adding

  1. set:- To set a value of a controller.(Supposing this has controller specific code)
  2. get:- To get a value of a controller.(Supposing this has controller specific code)
  3. adjust:- To validate the input and setting a controller.(Generic validations.. independent of controllers)
  4. user input mapping with controllers :- To get user input and invoking controllers accordingly.

Application Version 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;
        }

    }
    }
}

Now you have our first version of working application ready to be deployed. Time to analyze the work done so far.

Issues in TV Application Version 1

  1. Adjust(int value) code is duplicate in all three classes. You would like to minimize the code duplicity. (But you did not think of common code and moving it to some super class to avoid duplicate code)

You decide to live with that as long as your application works as expected.

After sometimes, your Boss comes back to you and asks you to add reset functionality to the existing application. Reset would set all 3 three controller to their respective default values.

You start writing a new class (ResetFunctionV2) for the new functionality and map the user input mapping code for this new feature.

Application Version 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;
            }

        }
    }
}

So you have your application ready with Reset feature. But, now you start realizing that

Issues in TV Application Version 2

  1. If a new controller is introduced to the product, you have to change Reset feature code.
  2. If the count of the controller grows very high, you would have issue in holding the references of the controllers.
  3. Reset feature code is tightly coupled with all the controllers Class’s code(to get and set default values).
  4. Reset feature class (ResetFunctionV2) can access other method of the Controller class’s (adjust) which is undesirable.

At the same time, You hear from you Boss that you might have to add a feature wherein each of controllers, on start-up, needs to check for the latest version of driver from company’s hosted driver repository via internet.

Now you start thinking that this new feature to be added resembles with Reset feature and Issues of Application (V2) will be multiplied if you don’t re-factor your application.

You start thinking of using inheritance so that you can take advantage from polymorphic ability of JAVA and you add a new abstract class (ControllerV3) to

  1. Declare the signature of get and set method.
  2. Contain adjust method implementation which was earlier replicated among all the controllers.
  3. Declare setDefault method so that reset feature can be easily implemented leveraging Polymorphism.

With these improvements, you have version 3 of your TV application ready with you.

Application Version 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;
            }

        }
    }
}

Although most of the Issue listed in issue list of V2 were addressed except

Issues in TV Application Version 3

  1. Reset feature class (ResetFunctionV3) can access other method of the Controller class’s (adjust) which is undesirable.

Again, you think of solving this problem, as now you have another feature (driver update at startup) to implement as well. If you don’t fix it, it will get replicated to new features as well.

So you divide the contract defined in abstract class and write 2 interfaces for

  1. Reset feature.
  2. Driver Update.

And have your 1st concrete class implement them as below

Application Version 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;
            }

        }
    }
}

Now all of the issue faced by you got addressed and you realized that with the use of Inheritance and Polymorphism you could

  1. Keep various part of application loosely coupled.( Reset or Driver Update feature components don’t need to be made aware of actual controller classes(Volume, Brightness and Colour), any class implementing OnReset or OnStart will be acceptable to Reset or Driver Update feature components respectively).
  2. Application enhancement becomes easier.(New addition of controller wont impact reset or driver update feature component, and it is now really easy for you to add new ones)
  3. Keep layer of abstraction.(Now Reset feature can see only setDefault method of controllers and Reset feature can see only checkForDriverUpdate method of controllers)

Hope, this helps :-)

Polymorphism is more likely as far as it's meaning is concerned ... to OVERRIDING in java

It's all about different behavior of the SAME object in different situations(In programming way ... you can call different ARGUMENTS)

I think the example below will help you to understand ... Though it's not PURE java code ...

     public void See(Friend)
     {
        System.out.println("Talk");
     }

But if we change the ARGUMENT ... the BEHAVIOR will be changed ...

     public void See(Enemy)
     {
        System.out.println("Run");
     }

The Person(here the "Object") is same ...

Polymorphism is a multiple implementations of an object or you could say multiple forms of an object. lets say you have class Animals as the abstract base class and it has a method called movement() which defines the way that the animal moves. Now in reality we have different kinds of animals and they move differently as well some of them with 2 legs, others with 4 and some with no legs, etc.. To define different movement() of each animal on earth, we need to apply polymorphism. However, you need to define more classes i.e. class Dogs Cats Fish etc. Then you need to extend those classes from the base class Animals and override its method movement() with a new movement functionality based on each animal you have. You can also use Interfaces to achieve that. The keyword in here is overriding, overloading is different and is not considered as polymorphism. with overloading you can define multiple methods "with same name" but with different parameters on same object or class.

Polymorphism relates to the ability of a language to have different object treated uniformly by using a single interfaces; as such it is related to overriding, so the interface (or the base class) is polymorphic, the implementor is the object which overrides (two faces of the same medal)

anyway, the difference between the two terms is better explained using other languages, such as c++: a polymorphic object in c++ behaves as the java counterpart if the base function is virtual, but if the method is not virtual the code jump is resolved statically, and the true type not checked at runtime so, polymorphism include the ability for an object to behave differently depending on the interface used to access it; let me make an example in pseudocode:

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

(supposing that makeRumor is NOT virtual)

java doesn't truly offer this level of polymorphism (called also object slicing).

animal a = new dog(); dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

on both case it will only print woff.. since a and b is refering to class dog

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());

    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top