Michel, Thank you for the explanations! Your reply did clear up some of the concerns I had regarding this PEP. I still have a few objections though: >> 1. What is the point of interfaces without static typing? >To assert a contract is one. To separate various implementations of the >same interface without them loosing a common usage is another. >No mandatory enforcement is being proposed. This means that interface support in Python will be limited to three applications: 1. Clear documentation of the interfaces 2. Separation of inheritence hierarchy from the implementation hierarchy 3. An ability to dtermine if a particular object supports a specific interface. Am I missing anything out? >> 2. At what point will the compliance with the interface definition be >> done, at compile time, or at run time? >There is no madatory compliance or interface enforcement proposed in 245. >These things are optional, and they should be optional. Turn on for >unit-testing, debugging, etc, turn off for production and speed. Great! >> If the compliance is checked at run time, then interface checking is as >> good as as simply assuming that the method is implemented. Today, I can >> compile code like "f.doSomething ()" without f actually implementing >> doSomething. At run time I would get an AttributeError thrown into my >> face. In fact, the run time compliance is available already. > >Interfaces, strong or weak, are not going to solve any of these problems >in a magic bullet fasion. There's a million ways around even strong >interfaced languaged, even ones that go so far as to check pre and >post-condition contract boundaries. I was not trying to identify the problems. On the contrary, my point was that run-time checking is supported today, i.e. if the method is not present, an AttributeError exception will be thrown. BTW. Are you planning on throwning an InterfaceError exception instead of AttributeError? >One of the major reasons for the PEP is to assert that an object can be >used in a certain way, without caring about how it is implemented. It's >telling you something about what it can do, without you having to know the >difference between the flat-file implementation and the one that uses a >relational database. >Currently this ability in Python is weak, and is based on looking at >classes. But classes are not meant to be explicit interfaces, they are >ways of sharing implementaiton. I see your point. But I think that proposed interface behavior is missing a very important attribute -- an explicit facility for acquiring interface references. Per you proposal, the reference to the object is indistinguishable from the reference to the interface. In Java the reference to the interface is obtained using a type cast, i.e. IProgrammer prg = (IProgrammer) obj; In COM, the same is accomplished through the use of QueryInterface, i.e. IProgrammer * pIProgrammer = NULL; HRESULT hr = pIObj->QueryInterface (IID_IProgrammer, reinterpret_cast<void**> (&pIProgrammer)); if (SUCCEEDED (hr)) ... or CComQIPtr<IProgrammer, &IID_IProgrammer> tIProgrammer(pIObj); if (!tIProgrammer) ... There is no such thing proposed in PEP 245. If the interfaces are added to Python, I would like to have a way of distinguishing between references to the object and references to the interface. In fact, I would like that to be more similar with COM rules where class implmenetor is responsible for the implementation of QueryInterface (although default behaviour should be provided). This permits playing all sorts of identity tricks, such as component aggregation, and tear-offs. How about adding __getinterfacereference__ that as name implies returns the interface reference? I guess a built-in getinterface (object, interface) -> interface reference would have to be added as well. >No, Java interfaces are just compile time enforcement. The syntax is >vaguely similar. But the concept is similar. Java interfaces assert a contract, and allow documenting it. In Java one can find out if class implements an interface. The syntax is extremely similar... Not that there is anything wrong with Java syntax. >Take me for example. If I were a python object, I'd be an instance of a >class that is generalized by two other classes, my mom and dad. That's my >type, my genetics. class Dad: ... class Mom: ... class Son (Dad, Mom): ... >Now, let's say you were a function that expected a >'Python programmer'. You could wire that expectation to my implementation >(my class), but then, I'd be the only "kind" of python programmer you could >use. You could wire it to my generalized classes, but then you could only >use me and my two sisters, and they're not python programmers. Let's say that a programmer does a number of tasks, among them are: 'writeRequirements', 'design', 'implement' In that case it is reasonable to expect that every programmer should implement those three methods. In which case I can write code like: # Client code son = Son () if has_attr (son, writeRequirements): son.writeRequirements () if has_attr (son, design): son.design () if has_attr (son, implement): son.implement () Assuming that I had interfaces, I would write: interface Programmer: """""" def writeRequirements (self): """""" def design (self): """""" def implement (self): """""" ... class Son (Dad, Mom) implements Programmer: ... # Client code son = Son () if implements (son, Programmer): son.writeRequirements () son.design () son.implement () What are the benefits of using the interface? Documentation is one of the biggest advantages. Also, an ability to ask the object if it implements interface as a whole comes in handy and reduces the number of if statements. Although the version of client code that uses exceptions is as simple. Now let's assume that there is an inexperienced programmer who does not write requirements yet, but is capable of doing everything else... It seems like our interface needs to be split up into two -- Analyst and Programmer interface Programmer: """""" def design (self): """""" def implement (self): """""" ... interface Analyst" """""" def writeRequirements (self): """""" class Son (Dad, Mom) implements Analyst, Programmer: ... # New client code son = Son () if implements (son, Analyst): son.writeRequirements () if implements (son, Programmer): son.design () son.implement () As you can see the client code had to change. Let's see what would client code withut interfaces look like? # Client code son = Son () if has_attr (son, writeRequirements): son.writeRequirements () if has_attr (son, design): son.design () if has_attr (son, implement): son.implement () As you can see, the version with if has_attr() still works just fine! (Assuming that has_attr works...) The point is -- the proposed definition of interfaces brings very little to the table. Everythinbg it offers can one way or another be done using existing language constructs. Sometimes, the use of interfaces introduces backward-compatibility problems. The biggest benefit that I see in the PEP 245 is the documentation. I like the fact that documentation will be structured in the form of the interface definition as oppose to a sparate help file. I also like an ability to determine if the object implements interface as a whole. But I can live without it using introspection. If the notion of "__getinterfacereference__" were added, I would see a lot more value in the PEP. Regards, Alex Shindich -- Posted from mailgw2.itginc.com [38.149.119.13] via Mailgate.ORG Server - http://www.Mailgate.ORG
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4