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 应该代表一个抽象类,而其他两个类应该从它继承,对我来说,它仍然看起来太难编码而不能成为抽象解决方案,我该如何改进?

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)

您可以在抽象类中指定默认值并覆盖 inRectangle或 in 中的方法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)

更新 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一篇关于这里的好帖子:什么是在 Python 中拥有多个构造函数的干净、pythonic 方式?

类型变量也无用,因为您可以使用它来识别类型:

>>> 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):
        ...

将使您的第一个功能被第二个“覆盖”。

作为一般的经验法则,通用 Base/Abstract 类的概念背后的主要思想是将实现与接口分离(注意 python 约定,函数名称的 lower_case_with_underscores,而不是 camleCase):

class Shape: 
  __metaclass__ = ABCMeta

  @abstractmethod
  def get_area(self):
    pass

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

现在我有了抽象但可操作的(如“每个形状都可以缩放、移动......”)基类,它完全不知道圆是如何构造、移动或缩放的。然后我可以开始实现子类:RectangleCircle,等等。

于 2012-04-22T17:50:27.717 回答