Hello
> A disposal interface has its issues.
Although Arnaud Le Blanc has already covered this topic thoroughly,
I’d like to approach it from a slightly different angle.
Let’s not think of __enter__/__exit__ + RefCount as a problem. Every
approach has its own purpose. In this case, there is a clear
distinction between Scope logic and __enter__/__exit__ logic. These
are two different concepts, and you cannot and should not try to
satisfy both RefCount and __enter__/__exit__ conditions at the same
time.
The purpose of __enter__/__exit__ is to handle the try-catch-finally
pattern for a resource regardless of the reference count. Therefore,
RefCount is not an issue.
(although PHP can automatically issue a warning when attempting to
call the method while the reference count is greater than one)
If PHP applies unset or __enter__/__exit__ depending on whether an
interface is implemented, it will introduce hidden behavior in the
code, making it harder for developers to understand what is happening.
Compare the two cases:
```php
// I know for sure that Scope implements the interface
// required to be used with "with"
with $scope = new Scope() {}
// I have no idea whether the File class implements
// the required interface or not. It’s unclear what will happen in the end.
with $file = new File("...") {}
```
So, in Python you cannot use arbitrary objects in a with statement,
only those that implement the __enter__ and __exit__ contract.
Therefore, in Python there is no ambiguity in the code. The developer
understands that if `with` is used, it means the object definitely
implements the required interface, otherwise an error will occur. PHP
must guarantee the same behavior.
P.S.
If I’m not mistaken, a recent RFC was proposed about context managers,
which covers exactly this logic.
---
Ed