面向对象编程的实践

有个产品,其有10个子产品,现在要统计每日消费数据
其中8个子产品的消费入账金额算法相同,2个不同;

拓展性差的糟糕的代码

def ConsumptionSum(product):
  product_id = product.get(product)
  if product == 'p1':
    return p1CS()
  if product == 'p2':
    return p2CS()

PEP 245 -- Python Interface Syntax | Python.org https://www.python.org/dev/peps/pep-0245/

PEP 245 -- Python Interface Syntax

PEP: 245
Title: Python Interface Syntax
Author: Michel Pelletier <michel at users.sourceforge.net>
Discussions-To: http://www.zope.org/Wikis/Interfaces
Status: Rejected
Type: Standards Track
Created: 11-Jan-2001
Python-Version: 2.2
Post-History: 21-Mar-2001

Formal Interface Syntax

Python syntax is defined in a modified BNF grammar notation described in the Python Reference Manual [8]. This section describes the proposed interface syntax using this grammar:

  1. interfacedef: "interface" interfacename [extends] ":" suite
  2. extends: "(" [expression_list] ")"
  3. interfacename: identifier
  4.  

This PEP also proposes an extension to Python's 'class' statement:

  1. classdef: "class" classname [inheritance] [implements] ":" suite
  2. implements: "implements" implist
  3. implist: expression-list
  4.  
  5. classname,
  6. inheritance,
  7. suite,
  8. expression-list: see the Python Reference Manual
  9.  

The Problem

Interfaces are important because they solve a number of problems that arise while developing software:

  • There are many implied interfaces in Python, commonly referred to as "protocols". Currently determining those protocols is based on implementation introspection, but often that also fails. For example, defining __getitem__ implies both a sequence and a mapping (the former with sequential, integer keys). There is no way for the developer to be explicit about which protocols the object intends to implement.
  • Python is limited, from the developer's point of view, by the split between types and classes. When types are expected, the consumer uses code like 'type(foo) == type("")' to determine if 'foo' is a string. When instances of classes are expected, the consumer uses 'isinstance(foo, MyString)' to determine if 'foo' is an instance of the 'MyString' class. There is no unified model for determining if an object can be used in a certain, valid way.
  • Python's dynamic typing is very flexible and powerful, but it does not have the advantage of static typed languages that provide type checking. Static typed languages provide you with much more type safety, but are often overly verbose because objects can only be generalized by common subclassing and used specifically with casting (for example, in Java).

There are also a number of documentation problems that interfaces try to solve.

  • Developers waste a lot of time looking at the source code of your system to figure out how objects work.
  • Developers who are new to your system may misunderstand how your objects work, causing, and possibly propagating, usage errors.
  • Because a lack of interfaces means usage is inferred from the source, developers may end up using methods and attributes that are meant for "internal use only".
  • Code inspection can be hard, and very discouraging to novice programmers trying to properly understand code written by gurus.
  • A lot of time is wasted when many people try very hard to understand obscurity (like undocumented software). Effort spend up front documenting interfaces will save much of this time in the end.

Interfaces try to solve these problems by providing a way for you to specify a contractual obligation for your object, documentation on how to use an object, and a built-in mechanism for discovering the contract and the documentation.

Python has very useful introspection features. It is well known that this makes exploring concepts in the interactive interpreter easier, because Python gives you the ability to look at all kinds of information about the objects: the type, doc strings, instance dictionaries, base classes, unbound methods and more.

Many of these features are oriented toward introspecting, using and changing the implementation of software, and one of them ("doc strings") is oriented toward providing documentation. This proposal describes an extension to this natural introspection framework that describes an object's interface.

Overview of the Interface Syntax

For the most part, the syntax of interfaces is very much like the syntax of classes, but future needs, or needs brought up in discussion, may define new possibilities for interface syntax.

A formal BNF description of the syntax is givena later in the PEP, for the purposes of illustration, here is an example of two different interfaces created with the proposed syntax:

  1. interface CountFishInterface:
  2. "Fish counting interface"
  3.  
  4. def oneFish():
  5. "Increments the fish count by one"
  6.  
  7. def twoFish():
  8. "Increments the fish count by two"
  9.  
  10. def getFishCount():
  11. "Returns the fish count"
  12.  
  13. interface ColorFishInterface:
  14. "Fish coloring interface"
  15.  
  16. def redFish():
  17. "Sets the current fish color to red"
  18.  
  19. def blueFish():
  20. "Sets the current fish color to blue"
  21.  
  22. def getFishColor():
  23. "This returns the current fish color"

This code, when evaluated, will create two interfaces called CountFishInterface and ColorFishInterface. These interfaces are defined by the interface statement.

The prose documentation for the interfaces and their methods come from doc strings. The method signature information comes from the signatures of the def statements. Notice how there is no body for the def statements. The interface does not implement a service to anything; it merely describes one. Documentation strings on interfaces and interface methods are mandatory, a 'pass' statement cannot be provided. The interface equivalent of a pass statement is an empty doc string.

You can also create interfaces that "extend" other interfaces. Here, you can see a new type of Interface that extends the CountFishInterface and ColorFishInterface:

  1. interface FishMarketInterface(CountFishInterface, ColorFishInterface):
  2. "This is the documentation for the FishMarketInterface"
  3.  
  4. def getFishMonger():
  5. "Returns the fish monger you can interact with"
  6.  
  7. def hireNewFishMonger(name):
  8. "Hire a new fish monger"
  9.  
  10. def buySomeFish(quantity=1):
  11. "Buy some fish at the market"

The FishMarketInteface extends upon the CountFishInterface and ColorfishInterface.

Interface Assertion

The next step is to put classes and interfaces together by creating a concrete Python class that asserts that it implements an interface. Here is an example FishMarket component that might do this:

  1. class FishError(Error):
  2. pass
  3.  
  4. class FishMarket implements FishMarketInterface:
  5. number = 0
  6. color = None
  7. monger_name = 'Crusty Barnacles'
  8.  
  9. def __init__(self, number, color):
  10. self.number = number
  11. self.color = color
  12.  
  13. def oneFish(self):
  14. self.number += 1
  15.  
  16. def twoFish(self):
  17. self.number += 2
  18.  
  19. def redFish(self):
  20. self.color = 'red'
  21.  
  22. def blueFish(self):
  23. self.color = 'blue'
  24.  
  25. def getFishCount(self):
  26. return self.number
  27.  
  28. def getFishColor(self):
  29. return self.color
  30.  
  31. def getFishMonger(self):
  32. return self.monger_name
  33.  
  34. def hireNewFishMonger(self, name):
  35. self.monger_name = name
  36.  
  37. def buySomeFish(self, quantity=1):
  38. if quantity > self.count:
  39. raise FishError("There's not enough fish")
  40. self.count -= quantity
  41. return quantity

面向对象、接口编程的重要性 python 为什么引入接口interface的更多相关文章

  1. 【PHP面向对象(OOP)编程入门教程】20.PHP5接口技术(interface)

    PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象 ...

  2. 吴裕雄--天生自然JAVA面向对象高级编程学习笔记:抽象类与接口的应用

    abstract class A{ // 定义抽象类A public abstract void print() ; // 定义抽象方法print() }; class B extends A { / ...

  3. PHP面向对象(OOP)编程入门教程

    面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...

  4. Mybatis接口编程原理分析(二)

    在上一篇博客中 Mybatis接口编程原理分析(一)中我们介绍了MapperProxyFactory和MapperProxy,接下来我们要介绍的是MapperMethod MapperMethod:它 ...

  5. 谈面向对象的编程(Python)

    (注:本文部分内容摘自互联网,由于作者水平有限,不足之处,还望留言指正.) 今天中秋节,也没什么特别的,寻常日子依旧. 谈谈面向对象吧,什么叫面向对象? 那么问题来了,你有对象吗?   嗯,,,那我可 ...

  6. python学习笔记--面向对象的编程和类

    一.面向对象的编程 面向对象程序设计--Object Oriented Programming,简称oop,是一种程序设计思想.二.面向对象的特性类:class类,对比现实世界来说就是一个种类,一个模 ...

  7. Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

  8. 【GoLang】golang 面向对象编程 & 面向接口编程

    005.面向对象&接口编程 1 面向函数编程 1.1 将数据作为参数传递到函数入参 1.2 对象与函数是分离的 2 面向对象编程 2.1 使用者看起来函数作为对象的属性而非参数 2.2 函数属 ...

  9. IT第十九天 - 继承、接口、多态、面向对象的编程思想

    IT第十九天 上午 继承 1.一般情况下,子类在继承父类时,会调用父类中的无参构造方法,即默认的构造方法:如果在父类中只写了有参的构造方法,这时如果在子类中继承时,就会出现报错,原因是子类继承父类时无 ...

随机推荐

  1. 判断一个字符串是否为合法IP

    输入任意一个字符串,判断是否为合法IP bool IsIPAddress(const char * str){ //先判断形式是否合法, //检查是否只包含点和数字 ; str[i] != '\0'; ...

  2. Rest API By JAX-RS 实现接口发布

    原文地址:http://www.cnblogs.com/oopsguy/p/7503589.html JAX-RS 我们在 JAX-RS 示例中使用相同的模型和 DAO,我们所需要做的只有更改 Sto ...

  3. php私有成员private的程序题目

    class base { private $member; function __construct() { echo __METHOD__ . "(begin)\n"; $thi ...

  4. Mybatis(三):MyBatis缓存详解

    MyBatis缓存分为一级缓存和二级缓存 一级缓存 MyBatis的一级缓存指的是在一个Session域内,session为关闭的时候执行的查询会根据SQL为key被缓存(跟mysql缓存一样,修改任 ...

  5. doT js模板入门 2

    doT js 使用{{}} 非常相似于JSP,所以用起来感觉非常亲切,非常顺手 {{–><% }}–>%> 比如: <div id="evaluationtmp ...

  6. 12.extern(转)

    本文转自:http://blog.csdn.net/xingjiarong/article/details/47656339 利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数 ...

  7. hMailServer 附件大小限制

    修改php.ini文件 1.post_max_size = 10M 表单提交最大数据为10M.此项不是限制上传单个文件的大小,而是针对整个表单的提交数据进行限制的. 2.file_uploads = ...

  8. linux下调试使用的 一些shell命令

    查看文件日期:strings |grep Build gdb g++ gcc make systemctl gdb: bt s n b 1.firewalld的基本使用 启动: systemctl s ...

  9. HDU - 5301 Buildings

    Buildings Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total S ...

  10. MySQL 5.7以上 root用户默认密码问题

    废话少说一句话系列: CentOS系统用yum安装MySQL的朋友,请使用 grep "temporary password" /var/log/mysqld.log 命令,返回结 ...