0

RectanglePython で単純なクラスを作成しようとしていますが、コードでポイントとサイズも使用する必要があるため、 RectanglefromPointSize. 問題は、私Rectangleの初期化メソッドが見栄えが悪く、それがどのコードにも適しているかどうかさえわからないことです。これが私が得たものです:

class Size:
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Rectangle(Size, Point):
    def __init__(self, size=None, position=None): #I'd rather not use 4 variables
        if size:
            super(Size, self).__init__(size.width, size.height)
        else:
            super(Size, self).__init__()
        if position:
            super(Point, self).__init__(position.x, position.y)
        else:
            super(Point, self).__init__()

ただし、見た目が悪く、機能しません。TypeError: object.__init__() takes no parameters

これを行うためのよりクリーンな方法はありますか?もちろん、四角形にsizeand position(オプションにするのではなく) を強制することもできますが、そうはしません。関係ではなく関係をRectangle持つように定義することもできますが、それは適切な OOP でさえありません。私は主にここで学んでいるので、どちらかをしたくありません。has-aSizePointis-a

4

3 に答える 3

3

使い方がsuper()間違っています。次の親クラスに到達するには、呼び出しで独自のクラスを指定します。他のすべてのクラスは同じことをする必要があります。あなたが今やっている方法では、 egSizeの親クラスを呼び出すように言っていますobject

これは Python 3 であるためsuper()、引数を指定しなくても実行でき、すべてが自動的に計算されます。

もちろん、これはsuper()、特定のクラスには が 1 つしかないため、必要に応じて を使用して両方の親クラスを明示的に呼び出すことができないことを意味しますsuper()。本当にそうしたい場合は、それらを as などで呼び出す必要がありますSize.__init__(self, ...)

しかし、あなたが作成した継承スキームは意味をなさないと言わざるを得ません。長方形は一種のサイズでも一種の点でもありません。代わりに、継承でなくカプセル化を示すものRectangleがあります (これらの特定のクラスのインスタンスであるsizeと属性、または実際には s)。カプセル化は確かに「適切な OOP」です。positionnamedtuple

于 2013-04-26T15:21:02.157 に答える
1

まず、あなたの質問に答えますhas-a。関係を続けてください。

class Rectangle:
    def __init__(self, size=None, position=None):
        self.size = size or Size()
        self.position = position or Point()

考えてみてください:長方形は位置とサイズですか、それとも長方形位置とサイズがありますか? 2D の長方形のみで構成されるゲームをコーディングしている場合は、答えがあります。読むのをやめてください。


...しかし、より多くの形状 ( などCircle) を使用する場合は、何かを行う前によく考えてください。OOP をコーディングするときは、常に何が必要かを考えることから始めます。したがって、最終的にはCircleクラスも必要になるかもしれません。-classをコーディングする前に、それと他の形状について考える必要がありますRectangle

CircleRectangle呼ばれる共通の属性がありますpositionShapeこれが、 orと呼ばれる基本クラスが必要な理由でGeometryあり、 atleast を定義しますposition

class Geometry:
    def __init__(self, position=None):
        self.position = position or Point()

class Rectangle(Geometry):
    def __init__(self, size=None, position=None):
        self.size = size or Size()
        super().__init__(position)

class Circle(Geometry):
    def __init__(self, radius=0, position=None):
        self.radius = radius
        super().__init__(position)

また、他にどのようなクラスがあるかを考えて、それらに共通の属性があるかどうかを確認します。

  • 三角形
  • 五角形
  • その他のポリゴン
  • ライン

あなたはすぐにposition、それらがすべて を持っていることに気付くでしょうGeometry。また、ある種のsize(線の長さ、円の半径、三角形の幅と高さ...) があるため、異なるものに対してもいくつかsizeの基本クラスを作成できます (三角形と長方形の幅と高さなど)。

于 2013-04-26T15:31:14.950 に答える
0

super()非常に特殊なユースケース、つまり、同じ__init__()変数を持つオブジェクトの階層があり、オブジェクト階層を完全に制御できない場合を対象としているため、それがどのように見えるか正確にはわかりません。

次に、 を使用しますsuper()

このケースは、ミックスイン クラスを含むライブラリを作成している場合に実際に発生します。__init__()理論上は可能ですが、同じパラメータを使用することはできず、super()うまく機能しません。

したがって、忘れてくださいsuper()。次のようにします。

class Size(object):
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

class Point(object):
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

class Rectangle(Size, Point):
    def __init__(self, x=0, y=0, width=0, height=0):
        Point.__init__(self, x, y)
        Size.__init__(self, width, height)

スーパーは見えません。(オブジェクトからすべてをサブクラス化することに注意してください。Python 3 では必要ありませんが、Python 2 がまだ広く使用されている限り、これは良い習慣です。)

しかし、はい、これは何らかの理由で、必要のない 4 つのパラメーターを使用します。それには2つの解決策があります。1 つは Markus の提案で、代わりに封じ込めを使用します。

class Rectangle(object):
    def __init__(self, size=None, position=None):
        self.size = size or Size()
        self.position = position or Point()

ただし、これは Point() と Size() のすべてのメソッドを Rectangle にも貼り付ける必要があることを意味します。もう 1 つの解決策は、少し賢く、非常に便利な組み込みの型、complex を使用することです。

class Point(object):
    def __init__(self, pos=0j):
        self.pos = pos

class Size(object):
    def __init__(self, size=0j):
        self.size = size

class Rectangle(Size, Point):
    def __init__(self, pos=0j, size=0j):
        Point.__init__(self, pos)
        Size.__init__(self, size)

2D グラフィックスに複素数を使用すると、大幅に簡素化されます。Point と Size クラスを用意する必要さえありません。complex を直接使用するだけです。

class Rectangle(object):
    def __init__(self, pos=0j, size=0j):
        self.pos = pos
        self.size = size

    def endpos(self):
        return self.pos + self.size


>>> r = Rectangle(5+3j, 3+7j)
>>> print(r.endpos())
(8+10j)

封じ込めの提案と同様に、サイズと位置ではなくサイズと位置あるため、これも優れています。これははるかに理にかなっています。

于 2013-04-26T19:12:12.060 に答える