Python - Nasljeđivanje (Inheritance)


Nasljeđivanje u Pythonu

Nasljeđivanje je značajan u objektno orijentiranom programiranju. Odnosi se na definisanje nove klase sa malo ili nimalo modifikacija postojeće klase. Nova klasa naziva se izvedena (ili podređena) klasa, a ona iz koje nasljeđuje naziva se osnovna (ili roditeljska) klasa.


Sintaksa nasljeđivanja Pythona

class BaseClass:
  Tijelo osnovne klase
class DerivedClass(BaseClass):
  Tijelo izvedene klase

Izvedena klasa nasljeđuje karakteristike od osnovne klase gdje joj se mogu dodati nove karakteristike. To rezultuje ponovnom upotrebom koda.


Primjer nasljeđivanja u Pythonu

Da pokažemo upotrebu nasljedstva, uzmimo primjer. Poligon je zatvorena figura s 3 ili više stranica. Recimo, imamo klasu zvanu Polygon definisanu na sljedeći način.

class Polygon:
    def __init__(self, no_of_sides):
        self.n = no_of_sides
        self.sides = [0 for i in range(no_of_sides)]

    def inputSides(self):
        self.sides = [float(input("Uđite sa strane "+str(i+1)+" : ")) for i in range(self.n)]

    def dispSides(self):
        for i in range(self.n):
            print("Strana",i+1,"is",self.sides[i])

Ova klasa ima atribute podataka za pohranjivanje broja stranica n i veličine svake strane kao liste koja se naziva stranice. Metoda inputSides() uzima veličinu svake strane dispSides() i prikazuje te dužine stranica. Trokut je mnogougao s 3 stranice. Dakle, možemo stvoriti klasu zvanu Triangle koja se nasljeđuje od Polygon. Ovo čini sve atribute klase Polygon dostupnima klasi Triangle. Ne trebamo ih ponovo definisati (ponovna upotreba koda). Trokut se može definisati kako što je prikazano u sljedećem primjeru.

class Triangle(Polygon):
    def __init__(self):
        Polygon.__init__(self,3)

    def findArea(self):
        a, b, c = self.sides
        # izračunavanje semi-perimeter
        s = (a + b + c) / 2
        area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
        print('Površina trokuta je %0.2f' %area)

Međutim, klasa Triangle ima novu metodu findArea() za pronalaženje i ispis područja trokuta. Evo primjera izvođenja.

>>> t = Triangle()

>>> t.inputSides()
Upiši stranu 1 : 3
Upiši stranu 2 : 5
Upiši stranu 3 : 4

>>> t.dispSides()
Strana 1 je 3.0
Strana 2 je 5.0
Strana 3 je 4.0

>>> t.findArea()
Površina trokuta je 6.00

Možemo vidjeti da, iako nismo zasebno definisali metode poput inputSides() ili dispSides() za klasu Triangle, mogli smo ih koristiti. Ako atribut nije pronađen u samoj klasi, pretraživanje se nastavlja na osnovnu klasu. Ovo se ponavlja rekurzivno, ako je osnovna klasa sama izvedena iz drugih klasa.



Nadjačavanje metode u Pythonu

U prethodnom primjeru, primijetite da je metoda __init__() definisana u obe klase, Triangle kao i Poligon. Kada se to dogodi, metoda u izvedenoj klasi poništava onu u osnovnoj klasi. Tada će, __init__() u Triangle dobiti prednost nad __init__ u Polygon. Generalno, kada nadjačavamo osnovnu metodu, težimo proširenju definicije umjesto da je jednostavno zamijenimo. Isto se radi pozivanjem metode u osnovnoj klasi iz one u izvedenoj klasi (pozivanje Polygon.__init__() iz __init__() u Triangle).

Bolja opcija bila bi upotreba ugrađene funkcije super(). Dakle, super().__ init__(3) je ekvivalentan Polygon.__init__(self, 3) i poželjniji je. Da biste saznali više o super() funkciji u Pythonu, posjetite Python super() funkciju. Dvije ugrađene funkcije isinstance() i issubclass() koriste se za provjeru nasljeđivanja. Funkcija isinstance() vraća True ako je objekt instanca klase ili drugih klasa izvedenih iz nje. Svaka klasa u Pythonu nasljeđuje od object osnovne klase.

>>> isinstance(t,Triangle)
True

>>> isinstance(t,Polygon)
True

>>> isinstance(t,int)
False

>>> isinstance(t,object)
True

Slično tome, issubclass() se koristi za provjeru nasljeđivanja klase.

>>> issubclass(Polygon,Triangle)
False

>>> issubclass(Triangle,Polygon)
True

>>> issubclass(bool,int)
True