Polümorfism

Polümorfism (ingl k polymorphism) on olukord, mille korral käitub meetod sõltuvalt klassist erinevalt.

Polümorfism esineb siis, kui alamklass kasutab superklassis defineeritud meetodit teisel moel. Teiste sõnadega: kui superklassil ja alamklassil on olemas sama nimega meetodid, millel on sama palju argumente, ning mis teevad erinevat asja, siis on tegemist polümorfismiga.

Näide polümorfismist

# Base or superclass
class Student:

    def say_hello(self):
        print("Hello!")


# Extending the base class
class ITStudent(Student):

    # Overriding the method with the same name from the base class
    def say_hello(self):
        print("Hello! Does anybody need help with their computer?")

    def assist_friend(self):
        print("Have you tried turning it off and on again?")


alice = Student()
mary = ITStudent()

alice.say_hello()  # --> Hello!
mary.say_hello()  # --> Hello! Does anybody need help with their computer?
mary.assist_friend()  # --> Have you tried turning it off and on again?

Kuna klass ITStudent on klassi Student alamklass ja meetod say_hello on defineeritud erinevalt ülemklassist, on tegu polümorfismiga. Sellist olukorda nimetatakse ülekirjutamiseks (override).

Polümorfism Pythoni lähtekoodis

Python kasutab polümorfismi näiteks operaatorite kasutamisel. Erinevate sisendite puhul käitub + operaator erinevalt.

  • Kahe arvu liitmisel liidetakse kaks arvu.

>>> 1 + 1
2
  • Kahe sõne liitmisel aga ühendatakse kaks sõna omavahel.

>>> "Foo " + "Bar"
'Foo Bar'
  • Kahe järjendi puhul ühendatakse samuti listid omavahel üheks järjendiks.

>>> [1, 2] + [3]
[1, 2, 3]

Samuti on ka meetodeid, mida saab välja kutsuda erinevat tüüpi andmete peal ja mille käitumine on vastavalt andmetele erinev.

>>> "Foo Bar".index("Bar")
4
>>> ["Foo", "Bar"].index("Bar")
1

Põhjalikum näide pärilikkusest ja polümorfismist

class Animal:
    """Animal class."""

    def __init__(self, name="None", is_pet=False):
        """
        Class constructor.

        :param name: animal name
        :param is_pet: pet or wild?
        """
        self.name = name
        self.is_pet = is_pet

    def speak(self):
        return "I cannot"

    def greet(self):
        return self.name + " greets you!"

    def is_friendly(self):
        return self.is_pet

    def __str__(self):
        return self.name


class Dog(Animal):
    """Class Dog exends class Animal"""

    def __init__(self, name, is_pet=True):
        """
        Class constructor.

        :param name: dog name
        :param is_pet: dog usually is a pet
        """
        # Overriding the base constructor, passing new values to self.is_pet and self.name
        super().__init__(name, is_pet)

    def roll(self):
        """
        Extra method, specific for this class.

        :return:
        """
        print("*rolling*")

    def speak(self):
        """
        Overriding the base method.
        By default it returns "I cannot", we change it to return "Bark!".

        :return: Bark!
        """
        return "Bark!"


class Dolphin(Animal):
    """Class Dolphin extends class Animal."""

    # Class constructor with two more arguments
    def __init__(self, name, playful, smart):
        """
        Class constructor with two extra parameters.

        :param name:
        :param playful
        :param smart
        """
        # Overriding the base constructor, passing new value to self.name
        super().__init__(name)

        self.playful = playful
        self.smart = smart

    def is_friendly(self):
        """
        Overriding the base method.
        By default if the animal is not a pet, it isn't friendly either. However in our case,
        if the dolphin is in playful mood or smart, it will be friendly to us.

        :return: boolean
        """

        return self.smart or self.playful

    def greet(self):
        """
        Overriding the base method.
        By default it returns "<name of the animal> greets you!". In our case it returns "*Water splash*".

        :return: *Water splash*
        """
        return "*Water splash*"

    def perform_jump(self):
        """
        Extra method, specific for this class.

        :return:
        """

        if self.playful:
            return "*Jumps*"

        elif self.smart:
            return "I will jump.. for food."

        return "No."


animal = Animal()
print(animal.is_pet)  # --> False
print(animal)  # --> None
print(animal.is_friendly())  # --> False
print(animal.greet())  # --> None greets you!
print(animal.speak())  # --> I cannot

print()

dog = Dog("Sparky")
print(dog.is_pet)  # --> True
print(dog)  # --> Sparky
print(dog.is_friendly())  # --> True
print(dog.greet())  # --> Sparky greets you!
print(dog.speak())  # --> Bark!
print(dog.roll())  # --> *rolling*

print()

dolphin = Dolphin("Steve", False, True)
print(dolphin.is_pet)  # --> False
print(dolphin)  # --> Steve
print(dolphin.is_friendly())  # --> True
print(dolphin.greet())  # --> *Water splash*
print(dolphin.speak())  # --> I cannot
print(dolphin.perform_jump())  # --> I will jump.. For food.