Hierarchia klas - Trójkąty

0

Mam zrobić takie zadanie:
screenshot-20200421214814.png

Doszedłem do czegoś takiego, a że nie za bardzo ogarniam jak działają klasy to chciałbym wiedzieć czy dobrze robię.

import math

class Trojkat:
    
    def __init__(self, a, b, c):
        self.a=a
        self.b=b
        self.c=c
        
    def pole(self):
            s=(self.a+self.b+self.c)/2
            pole=math.sqrt(s*(s-self.a)*(s-self.b)*(s-self.c))
            return pole
    
    def obwod(self):
        return self.a + self.b + self.c
    
    def wysokosc(self):
        wysokosc = (2*pole)/self.a
        return wysokosc

    
class TrojkatProstakatny(Trojkat):
    
    def __init__(self, l, w):
        self.l=l
        self.w=w
        
    def pole(self):
        return self.l * self.w
    
    def obwod(self):
        return 2*(self.w + self.l)
    
    
class TrojkatRownoboczny(TrojkatProstakatny):
    
    def __init__(self, a):
        b=a
        c=a
        super().__init__(a,b,c)
        
    def pole(self):
        pole=math.sqrt(3)*pow(self.a,2)/4
        return pole
        
    def obwod(self):
        return 3*(self.a)
    
    def wysokosc(self):
        P = super(TrojkatRownoboczny,self).pole()
        wysokosc = (2*P)/self.a
        return wysokosc
    
class TrojkatRownoramienny(TrojkatRownoboczny):
1

Zgodnie z tą hierarchią, która jest na obrazku, klasy powinny wyglądać podobnie do:

class Figura:
    ...

class Trojkat(Figura):
    ...

class TrojkatProstokatny(Trojkat):
    ...

class TrojkatRownoboczny(Trojkat):
    ...

class TrojkatRownoramienny(Trojkat):
    ...
1

Z tego, co rozumiem Trojkat ma dziedziczyć jeszcze po Figura. W tej klasie możesz poopisywać, że wszystkie subklasy mają implementować pole i obwod (bo każda figura będzie miał pole i obwód). Nie wiem, co znaczy "czy_wiekszy_od" bazując na obwodzie, ale może chodzi o porównywanie obwodów.

class Figura:
    def pole(self):
        raise NotImplementedError()

    def obwod(self):
        raise NotImplementedError()

    def czy_wiekszy_od(self, other): 
        return self.obwod() > other.obwod()

W klasie Trojkat oprócz dziedziczenia po Figura wiele się nie zmieni założę, że wzory są ok. class Trojkat(Figura): ...
Jeżeli chodzi o dziedziczenie TrojkatRownoboczny po Trojkat, to słaby pomysł. Teoretycznie wystarczyłoby, żeby TrojkatRownoboczny wywoływał superkonstruktor:

class TrojkatRownoboczny(Trojkat):  # Zauważ, że zadanie mówi, żeby `TrojkatRownoboczny` dziedziczył po `Trojkat` a nie `TrojkatProstakatny`
    def __init__(self, a):
        super().__init__(a, a, a)

I to powinno wystarczyć, bo obliczanie pola/obwodu zaimplementowane w klasie Trojkat powinno dać sobie radę z trójkątem równobocznym.
Ale jak mówiłem, to słaby pomysł i tak nie powinno się robić. Zauważ, że teraz możesz stworzyć TrojkatRownoboczny, zmienić mu jeden z atrybutów i już nie masz poprawnego trójkąta równobocznego

trojkatRownoboczny = TrojkatRownoboczny(10)
trojkatRownoboczny.b = 20

A jeżeli chodzi o docstringu w stylu numpy - https://numpydoc.readthedocs.io/en/latest/format.html

0

Mam coś takiego:

import math
class Figura:
    
    def pole(self):
        raise NotImplementedError()

    def obwod(self):
        raise NotImplementedError()

    def wysokosc(self):
        raise NotImplementedError()
        
    def czy_wiekszy_od(self, other): 
        return self.obwod() > other.obwod()
    
class Trojkat(Figura):
    
    def __init__(self, a, b, c):
        self.a=a
        self.b=b
        self.c=c
        
    def pole(self):
            s=(self.a+self.b+self.c)/2
            pole=math.sqrt(s*(s-self.a)*(s-self.b)*(s-self.c))
            return pole
    
    def obwod(self):
        return self.a + self.b + self.c
    
    def wysokosc(self):
        s=(self.a+self.b+self.c)/2
        pole=math.sqrt(s*(s-self.a)*(s-self.b)*(s-self.c))
        wysokosc = (2*pole/self.a)
        return wysokosc
    
    def czy_wiekszy_od(self, other):
        return self.obwod() > other.obwod()
    
class TrojkatProstakatny(Trojkat):
    
    def __init__(self, l, w):
        self.l=l
        self.w=w
        
    def pole(self):
        return (self.l * self.w)/2
    
    def obwod(self):
        return 2*(self.w + self.l)
    
    def czy_wiekszy_od(self, other):
        return self.obwod() > other.obwod()
    
    
class TrojkatRownoboczny(Trojkat):
    
    def __init__(self, a):
        super().__init__(a,a,a)
        
    def czy_wiekszy_od(self, other):
        return self.obwod() > other.obwod()
    
class TrojkatRownoramienny(Trojkat):
    
    def __init__(self, a,c):
        super().__init__(a,a,c)
        
    def wysokosc(self):
        wysokosc = math.sqrt(pow(self.a, 2) - pow(self.c/2, 2))
        return wysokosc
  
    def czy_wiekszy_od(self, other):
        return self.obwod() > other.obwod()

Chce zrobić TrojkatProstokatny ale nie do końca wiem co ma dziedziczyć po Trojkat, żeby działało jak trzeba.

1

Nie kopiuj czy_wiekszy_od do wszystkich subklas. Ta metoda jest już zaimplementowana w klasie Figura i wszystkie jej subklasy będą mogły jej używać.
TrojkatProstokatny to rzeczywiście zagwostka. Możesz sprawdzać czy trójkąt jest rzeczywićie prostokątny i rzucać wyjątkiem jeżeli nie

import math

class TrojkatProstokatny(Trojkat):
    @staticmethod
    def __is_right(a, b, c):
        sides = sorted([a, b, c])  # przyprostokątne powinny być krótsze od przeciwprostokątnej 
        return math.isclose(sides[0] ** 2 + sides[1] ** 2, sides[2] ** 2)  # pitagoras powinien się zgadzać
    
    def __init__(self, a, b, c):
        if not self.__is_right(a, b, c):
            raise ValueError("Opisz błąd")
        super().__init__(a, b, c)

EDIT: ewentualnie możesz przyjmować rozmiary przyprostokątnych i obliczać przeciwprostokątną

class TrojkatProstokatny(Trojkat):
    def __init__(self, a, b):
        super().__init__(a, b, math.sqrt(a ** 2 + b ** 2))
0

Okej poprawiłem, dzięki wielkie. A jakiś pomysł co do tego czemu liczenie wysokości nie działa w TrojkatRownoramienny?

class TrojkatRownoramienny(Trojkat):
    
    def __init__(self, a,b):
        super().__init__(a,b,a)

1 użytkowników online, w tym zalogowanych: 0, gości: 1