Problem dijamanta javlja se kada razred nasljeđuje od dva razreda koji dijele zajedničkog pretka, što stvara nejasnoću: ako oba srednja razreda nadjačaju metodu (ili drže polje), koju verziju dobiva donji razred?
Dijamant
A (defines greet())
/ \
B C (each may override greet())
\ /
D ← inherits from B and C: which greet()?
U Python-u (koji dozvoljava višestruko nasljeđivanje)
class A:
def greet(self): return "A"
class B(A):
def greet(self): return "B"
class C(A):
def greet(self): return "C"
class D(B, C): # multiple inheritance
pass
print(D().greet()) # "B" — resolved by MRO, not ambiguous
print(D.__mro__) # D → B → C → A → object (C3 linearization)
Python to rješava determinističkim putem preko Redoslijeda razrješivanja metoda (MRO) koristeći C3 linearizaciju, a super() surađuje s tim redoslijedom.
Kako jezici to rješavaju
| Jezik | Pristup |
|---|---|
| C++ | Dozvoljava; nejasnoća je greška pri kompajliranju osim ako ne kvalificirate, ili koristite virtual nasljeđivanje za dijeljenje jedne baze |
| Java/C# | Zabranjuju višestruko nasljeđivanje razreda; dopuštaju višestruko sučelje (nema stanja, dakle nema dijamanta podataka) |
| Python | Dozvoljava; rješava preko MRO (C3) |
| Scala | Osobine s definiranim redoslijedom linearizacije |
Zamka
Čak i s MRO, višestruko nasljeđivanje stanja brzo postaje zbunjujuće — duplirano inicijaliziranje baze, iznenađujući super() lanci. Sučelja/osobine (ponašanje, ne stanje) zaobilaze većinu problema.
Zašto je to važno
Objašnjava glavni jarak u dizajnu jezika: Java i C# su posebno zabranili višestruko nasljeđivanje razreda kako bi izbjegli ovu nejasnoću, nudeći sučelja umjesto toga.
Razumijevanje MRO je praktično u Python-u: kooperativni super() i redoslijed mixin-a imaju smisla samo kada vidite kako je dijamant lineariziran.
