我无法找出建模此问题的正确方法。 在这里,我给你一个我的代码的简约版本:
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
class AreaCalculator():
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getArea(self):
pass
def compute(self):
self.getArea()
class PerimeterCalculator():
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getPerimeter(self):
pass
def compute(self):
self.getPerimeter()
class TriangleAreaCalculator(AreaCalculator):
def __init__(self):
AreaCalculator.__init__(self)
def getArea(self):
return area
class TrianglePerimeterCalculator(PerimeterCalculator):
def __init__(self):
PerimeterCalculator.__init__(self)
def getPerimeter(self):
return perimeter
a = TriangleAreaCalculator()
b = TrianglePerimeterCalculator()
是否有一种优雅的方式来合并" TrianglePerimeterCalculator"和" TriangleAreaCalculator"课程分为一部分,但保持" PerimeterCalculator"和" AreaCalculator"分离
[编辑]正如Kyle在评论中所建议的那样,我可以创建一个新的类(让我们称之为" Triangle")继承自" PerimeterCalculator"和" AreaCalculator"同时,但我想要的是能够告诉一个新的" Triangle"表现为" PerimeterCalculator"或" AreaCalculator",但不能同时进行。
答案 0 :(得分:2)
我认为"设计模式"你应该使用的是多重继承。下面是您的代码的修改版本,演示了它是如何做的(加上一些其他更改使其实际可运行,所有类都是新风格)。
from abc import ABCMeta, abstractmethod
class AreaCalculator(object):
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getArea(self):
pass
def compute(self):
self.getArea()
class PerimeterCalculator(object):
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getPerimeter(self):
pass
def compute(self):
self.getPerimeter()
class TriangleAreaCalculator(AreaCalculator):
def __init__(self):
super(TriangleAreaCalculator, self).__init__()
def getArea(self):
print('TriangleAreaCalculator.getArea() called on instance of {}'.format(
self.__class__.__name__))
# return area
return 13
class TrianglePerimeterCalculator(PerimeterCalculator):
def __init__(self):
super(TrianglePerimeterCalculator, self).__init__()
def getPerimeter(self):
print('TrianglePerimeterCalculator.getPerimeter() called on instance of {}'.format(
self.__class__.__name__))
# return perimeter
return 42
class MergedCalculator(TriangleAreaCalculator, TrianglePerimeterCalculator):
def __init__(self):
super(MergedCalculator, self).__init__()
merged = MergedCalculator()
print('merged.getArea() -> {}'.format(merged.getArea()))
print('merged.getPerimeter() -> {}'.format(merged.getPerimeter()))
输出:
TriangleAreaCalculator.getArea() called on instance of MergedCalculator
merged.getArea() -> 13
TrianglePerimeterCalculator.getPerimeter() called on instance of MergedCalculator
merged.getPerimeter() -> 42
答案 1 :(得分:1)
在编辑和澄清您的问题之后,这是另一个答案。它允许根据需要创建单个 Triangle
实例,其行为可以像AreaCalculator
或PerimeterCalculator
。
这种编程模式称为"委托"并且用于将实现特定操作的责任移交给另一个对象的地方 - 在这种情况下是一个其他类的内部持有的实例。在Python中执行此操作的常用方法是覆盖类的默认__getattr__()
方法。
由于您从未在我的其他答案中回复有关控制使用哪种行为的确切内容的评论,因此我添加了set_behavior()
方法以允许明确指定。
from abc import ABCMeta, abstractmethod
class AreaCalculator:
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getArea(self):
pass
def compute(self):
return self.getArea()
class PerimeterCalculator:
__metaclass__ = ABCMeta
def __init__(self):
pass
@abstractmethod
def getPerimeter(self):
pass
def compute(self):
return self.getPerimeter()
class TriangleAreaCalculator(AreaCalculator):
def __init__(self):
super(TriangleAreaCalculator, self).__init__()
def getArea(self):
print('TriangleAreaCalculator.getArea() called')
area = 13
return area
class TrianglePerimeterCalculator(PerimeterCalculator):
def __init__(self):
super(TrianglePerimeterCalculator, self).__init__()
def getPerimeter(self):
print('TrianglePerimeterCalculator.getPerimeter() called')
perimeter = 42
return perimeter
class Triangle:
def __init__(self):
delegate_classes = TriangleAreaCalculator, TrianglePerimeterCalculator
# Map delegate classes to instances of themselves.
self._delegates = {delegate_class: delegate_class()
for delegate_class in delegate_classes}
self.set_behavior(TriangleAreaCalculator) # Set default delegate.
def __getattr__(self, attrname):
# Called only for attributes not defined by this class (or its bases).
# Retrieve attribute from current behavior delegate class instance.
return getattr(self._behavior, attrname)
def set_behavior(self, delegate_class):
try:
self._behavior = self._delegates[delegate_class]
except KeyError:
raise TypeError("{} isn't a valid {} behavior delegate class"
.format(delegate_class, self.__class__.__name__))
if __name__ == '__main__':
triangle = Triangle()
# Uses instance's default behavior.
print('triangle.compute() -> {}'.format(triangle.compute()))
triangle.set_behavior(TrianglePerimeterCalculator) # Change behavior.
print('triangle.compute() -> {}'.format(triangle.compute()))
输出:
TriangleAreaCalculator.getArea() called
triangle.compute() -> 13
TrianglePerimeterCalculator.getPerimeter() called
triangle.compute() -> 42
答案 2 :(得分:0)
我自己想出来,灵感来自Kyle和martineau的评论/答案。
我可以创建一个合并的类“Triangle”,如下所示:
private void create_ans_btns(string newWord)
{
LinearLayout ll = (LinearLayout)FindViewById(Resource.Id.linearLayout);
Button[] ans_btn = new Button[newWord.Length];
for (int counter = 0; counter < newWord.Length; counter++)
{
ans_btn[counter] = new Button(this);
ans_btn[counter].Id = counter;
ans_btn[counter].Text = "" + counter;
ans_btn[counter].SetHeight(50);
ans_btn[counter].SetWidth(50);
ll.AddView(ans_btn[counter]);
/*
ans_btn[counter].Click += delegate { ans_btn[counter].Text = ""; };
*/
}
}
然后按如下方式修改TriangleAreaCalculator和TrianglePerimeterCalculator:
class Triangle():
def __init__(self):
pass
def getTriangleArea(self):
print 'Triangle area'
def getTrianglePerimeter(self):
print 'Triangle perimeter'
这样,我可以创建一个新的类似Triangle的实例,其行为为“PerimeterCalculator”或“AreaCalculator”(但不是同时):
class TriangleAreaCalculator(AreaCalculator, Triangle):
def __init__(self):
TriangleCalculator.__init__(self)
AreaCalculator.__init__(self)
def getArea(self):
super(TriangleAreaCalculator, self).getTriangleArea()
class TrianglePerimeterCalculator(PerimeterCalculator, Triangle):
def __init__(self):
TriangleCalculator.__init__(self)
PerimeterCalculator.__init__(self)
def getPerimeter(self):
super(TrianglePerimeterCalculator, self).getTrianglePerimeter()