2013-07-11 13 views
31

Moja wiedza w języku Python jest ograniczona, potrzebuję pomocy w następującej sytuacji.Dynamicznie wybierając klasę dziedziczącą po

Załóżmy, że mam dwie klasy A i B, jest to możliwe, aby zrobić coś jak następuje (koncepcyjnie) w Pythonie:

import os 
if os.name == 'nt': 
    class newClass(A): 
     # class body 
else: 
    class newClass(B): 
     # class body 

Tak więc problem jest to, że chciałbym, aby utworzyć klasę newClass takie że będzie dziedziczyć po różnych klasach bazowych na podstawie różnicy między platformami, czy można to zrobić w Pythonie? Dzięki.

Odpowiedz

55

Można użyć conditional expression:

class newClass(A if os.name == 'nt' else B): 
    ... 
+2

+1 mnie uprzedził . ;) –

+1

Więc ... Piękna. – corazza

+9

Panie i panowie, posłuchajmy go dla Pythona. –

12

Tak, można zrobić dokładnie to, co napisałeś. Choć osobiście, prawdopodobnie zrobić to w ten sposób czystość:

class _newClassNT(A): 
    # class body 

class _newClassOther(B): 
    # class body 

newClass = _newClassNT if os.name == 'nt' else _newClassOther 

ta zakłada, że ​​trzeba robić różne rzeczy faktycznie realizacja mądry w ciele klasy. Jeśli tylko trzeba zmienić dziedziczenia, można po prostu umieścić oświadczenie if tam:

class newClass(A if os.name == 'nt' else B): 
    # class body 
+0

Wielkie dzięki za pomoc! – taocp

+0

dlaczego to zrobić zamiast przypisywać A lub B do 'BaseCls' w oparciu o warunek, a następnie' class newClass (BaseCls) '? – cowbert

4

Jadąc ze świata Java i C#, myśl robi coś takiego sprawia, że ​​warować = P. (Nie jest tak, że pomysł warunkowego dziedziczenia klasy jest zły - po prostu nie jestem do tego przyzwyczajony.)

Myśląc o tym przez chwilę, zrobiłbym coś takiego, jeśli to pytanie dotyczyło Javy. Jestem delegowania wzór - implementować interfejs, a następnie użyć fabrykę, aby wybrać pomiędzy wdrożeń - w celu zapewnienia innego punktu widzenia problemu:

public interface OsDependent { 
    public void doOsDependentStuff(); 
} 

public class WindowsDependentComponent implements OsDependent { 
    @Override 
    public void doOsDependentStuff() { 
    //snip 
    } 
} 

public class AppleDependentComponent implements OsDependent { 
    @Override 
    public void doOsDependentStuff() { 
    //snip 
    } 
} 

public class OsDependentComponentFactory { 
    public OsDependent getOsDependentComponent(Platform platform) { 
    if(platform == Platform.WINDOWS) 
     return new WindowsDependentComponent(); 
    else if(platform == Platform.APPLE) 
     return new AppleDependentComponent(); 
    else 
     return null; 
    } 
} 

pewno dużo więcej kodu, ale jest to właściwe rozwiązanie w mocno wpisane środowisko.


EDIT: Jedna istotna różnica między zauważyłem moją odpowiedź i oryginalne pytanie:

Jeśli warunkowo dziedziczyć z wielu różnych klas, wówczas superklasy zawierać kod, który zależy od rodzaju systemu operacyjnego używasz, podczas gdy klasa, która dziedziczy po nich, zawiera kod, który jest taki sam dla wszystkich systemów operacyjnych. Górna część łańcucha dziedziczenia zależy od systemu operacyjnego; dno nie jest.

Moje podejście idzie w drugą stronę. Interfejs (lub superklasa) OsDepndent definiuje metody, które są podobne dla wszystkich platform, podczas gdy różne implementacje (lub podklasy) mają kod zależny od systemu operacyjnego. Górny łańcuch dziedziczenia jest niezależny od OS.

+0

Zdecydowanie wolę to rozwiązanie (przekształcone na pythona) lub Henry Keiter. Chociaż arshajii jest ładny i prosty, może obsługiwać tylko dwa różne typy systemów operacyjnych, więc nie jest "bezpieczny w przyszłości" i jak wskazał Robert C. Martin w swojej wspaniałej książce (Clean Code), lepiej być bezpiecznym, niż żałować. Python działa na zbyt wielu różnych platformach, aby zignorować ten fakt ... – tamasgal

2

Znalazłem własny sposób dynamicznego dziedziczenia klas, gdy masz więcej niż dwie opcje do wyboru. Jestem pewien, że inni używali tego przede mną, jednak nie mogłem znaleźć czegoś takiego w Internecie, dlatego pomyślałem, że powinienem się z wami podzielić.

class A(): 
    # Class A Body 
class B(): 
    # Class B Body 
class C(): 
    # Class C Body 
class D(): 
    # Class D Body 
def MakeObject(InheritedClassName): # InheritedClassName is a string 
    def CheckClass(InheritedClass): 
     if InheritedClass == "A": 
      return A 
     elif InheritedClass == "B": 
      return B 
     elif InheritedClass == "C": 
      return C 
     else: 
      return D 
    class WantedClass(CheckClass(InheritedClassName)): 
     # WantedClass Body 
    YourObject = WantedClass() 
    return YourObject 
CreateObject = MakeObject(str(input("Chose A, B, C or D"))) 

Ten kod można zmienić i można z nim zrobić wiele.To jest mój ulubiony sposób konfigurowania dziedziczenia klasy dynamicznej, mimo że jest trochę długi, ponieważ możesz mieć tyle opcji, ile chcesz, a nawet mieć wiele dynamicznie wybranych dziedziczeń dla każdego obiektu.

1

Dla tych, którzy mają podobne potrzeby podczas pracy z różnymi modułami. Najpierw utwórz plik switcher.py i umieścić wewnątrz niego następujące

class Switcher(): 
    def choose(clname): 
     Switcher.clname = clname 

Następnie w swojej newClass.py umieścić

import switcher 

class newClass(switcher.Switcher.clname): 
    ... 

Wreszcie w głównym skrypcie

import switcher 
import os 
    if os.name == 'nt': 
     switcher.Switcher.choose(A): 
    else: 
     switcher.Switcher.choose(B): 

# that's the moment you're creating class with desired inheritance 
import newClass.newClass 
Powiązane problemy