3
import math
class Point:

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def move(self,x,y):
        self.x += x
        self.y += y

    def __str__(self):
        return "<"+ str(self.x) + "," + str(self.y) + ">"


class Shape:        
    def __init__(self, centrePoint, colour, width, height):
        self.centrePoint = centrePoint
        self.colour = colour
        self.width = width
        self.height = height
        self.type = "Square"

    def __init__(self, centrePoint, radius, colour):
        self.type = "Circle"
        self.radius = radius
        self.colour = colour
        self.centrePoint = centrePoint

    def move(self,x,y):
        self.centrePoint.move(x,y)

    def getArea(self):
        if (self.type == "Square"):
            return self.width * self.height
        elif (self.type == "Circle"):
            return math.pi*(self.radius**2)

    def __str__(self):
        return "Center Point: " + str(self.centrePoint) + "\nColour: "+ self.Colour + "\nType: " + self.type + "\nArea: " + self.getArea()


class Rectangle (Shape):

    def scale(self, factor):
        self.scaleVertically(factor)
        self.scaleHorizontally(factor)

    def scaleVertically(self, factor):
        self.height *= factor

    def scaleHorizontally(self, factor):
        self.width *= factor

class Circle (Shape):

    def scale(self, factor):
        self.radius * factor

それは私がこれまでに持っているコードです。Shape は抽象クラスを表し、他の 2 つのクラスはそれを継承することになっています。私にはまだハードコーディングされすぎて抽象ソリューションにはなりません。どうすれば改善できますか?

4

2 に答える 2

4

抽象クラスのこの部分を変更します。

def getArea(self):
    if (self.type == "Square"):
        return self.width * self.height
    elif (self.type == "Circle"):
        return math.pi*(self.radius**2)

抽象クラスでデフォルトを指定し、メソッドをRectangleまたはでオーバーライドできますCircle

ただし、 https://codereview.stackexchange.com/でより良い回答が得られる場合があります。

更新 (例):

from abc import ABCMeta, abstractmethod

class Shape: 
  __metaclass__ = ABCMeta

  @abstractmethod
  def getArea(self):
    pass

class Rectangle (Shape):
  def getArea(self):
    return self.width * self.height

class Circle (Shape):
  def getArea(self):
    return math.pi*(self.radius**2)

UPDATE 2 (関数のオーバーロード)

Ohadが書いたように、オーバーロードは Python では機能しません。ここでは、init 関数をオーバーロードしない例を示します。

def Shape:
  def __init__(self, centrePoint, colour, **kwargs):
    self.centrePoint = centrePoint
    self.colour      = colour
    self.width       = kwargs.get('width')
    self.height      = kwargs.get('height')
    self.radius      = kwargs.get('radius')

これで、オブジェクトを作成できます

rect = Rectangle(0, "red", width=100, height=20)
circ = Circle(0, "blue", radius=5)

良い投稿kwargsはここにあります: What is a clean, pythonic way to have multiple constructors in Python?

これを使用して型を識別できるため、型変数も役に立ちません。

>>> rect = Rectangle(...)
>>> print isinstance(rect, Rectangle)
True
>>> print isinstance(rect, Circle)
False
于 2012-04-22T16:45:56.557 に答える
2

まず、Python には関数のオーバーロードがないことに注意してください。したがって、次のようになります。

class Shape:        
    def __init__(self, centrePoint, colour, width, height):
        ...

    def __init__(self, centrePoint, radius, colour):
        ...

最初の関数を2番目に「オーバーライド」します。

一般的な経験則として、共通の Base/Abstract クラスの概念の背後にある主なアイデアは、インターフェイスから実装を分離することです (Python の規則に注意してください。関数名は camleCase ではなく、lower_case_with_underscores です)。

class Shape: 
  __metaclass__ = ABCMeta

  @abstractmethod
  def get_area(self):
    pass

  move, scale, scale_vertically, scale_horizontally, print...

これで、円がどのように構築、移動、またはスケーリングされるかを完全に認識しない、抽象的でありながら操作可能な (「すべての形状をスケーリング、移動できます..」のように) 基本クラスができました。Rectangleその後、 、 などのサブクラスの実装を開始できCircleます。

于 2012-04-22T17:50:27.717 に答える