2017-02-07 2 views
2

У меня есть следующий Python 3.6 Код:избежать дублирования проверки на подклассы

import abc 
import math 
from abc import ABC 


class Shape(ABC): 
    @abc.abstractmethod 
    def draw(self, area): 
     pass 


class Square(Shape): 
    def draw(self, area): 
     if area < 0: 
      raise ValueError('Area must be greater or equal than 0.') 

     print('Square. Side length: %s' % math.sqrt(area)) 


class Circle(Shape): 
    def draw(self, area): 
     if area < 0: 
      raise ValueError('Area must be greater or equal than 0.') 

     print('Circle. radius: %s' % math.sqrt(area/math.pi)) 

Как я могу избежать повторения той же проверки на каждом подклассе?

ответ

1

использовать базовый класс для создания методы проверки, что вы используете в подклассах

import abc 
import math 
from abc import ABC 


class Shape(ABC): 
    @abc.abstractmethod 
    def draw(self, area): 
     pass 
    def _check_area(area): 
     if area < 0: 
      raise ValueError('Area must be greater or equal than 0.') 


class Square(Shape): 
    def draw(self, area): 
     self._check_area(area) 
     print('Square. Side length: %s' % math.sqrt(area)) 


class Circle(Shape): 
    def draw(self, area): 
     self._check_area(area) 
     print('Circle. radius: %s' % math.sqrt(area/math.pi)) 

(я использовал один префикс подчеркивания сигнализировать потенциальные пользователь, что это внутренний метод, не будучи на самом деле частью интерфейса класса)

Или, может быть, даже лучше: создайте внутренний метод _draw, который будет абстрактным, а не методом draw. Таким образом, вы можете проверить площадь в draw и вызвать _draw в базовом классе:

import abc 
import math 
from abc import ABC 


class Shape(ABC): 
    def draw(self, area): 
     if area < 0: 
      raise ValueError('Area must be greater or equal than 0.') 
     self._draw 

    @abc.abstractmethod 
    def _draw(self, area): 
     pass 


class Square(Shape): 
    def _draw(self, area): 
     print('Square. Side length: %s' % math.sqrt(area)) 


class Circle(Shape): 
    def _draw(self, area): 
     print('Circle. radius: %s' % math.sqrt(area/math.pi)) 
+0

Спасибо! Я только что отредактировал ваше второе решение, я думаю, вы забыли удалить self._check_area (область) из подклассов. Еще раз спасибо. –