[RFC] Abstract final classes

php.internals

Guilherme Blanco

11 years ago
Hi, I worked on an implementation of a somehow controversial concept that exists in hack and C#: abstract final classes. https://wiki.php.net/rfc/abstract_final_class My motivation is to further expand class support to add modifiers (PPP - public, protected, private). I added this change to initially segregate grammar rules. It was an easy feature without extensive complexity and covers some use-cases. As a reference, here is the commit hash that added this feature to Hack: https://github.com/facebook/hhvm/commit/faedfaf46b0deb859b0c20fb36a574be7a4f2f55 Cheers,
-- Guilherme Blanco MSN: guilhermeblanco@hotmail.com GTalk: guilhermeblanco Toronto - ON/Canada

Marco Pivetta

11 years ago
Except for the H1 on the RFC (needs to be updated), I can really see a lot of cases where I needed this: badly. On Nov 27, 2014 4:48 AM, "guilhermeblanco@gmail.com" < guilhermeblanco@gmail.com> wrote:

Stas Malyshev

11 years ago
Hi!
> I worked on an implementation of a somehow controversial concept that > exists in hack and C#: abstract final classes. > > https://wiki.php.net/rfc/abstract_final_class
In the RFC, I think one phrase needs clarification: Currently, PHP developers' only resource is to create a final class with a private constructor, leading to untestable and error prone code. What is "error prone" in private __construct(); and how the RFC improves the testability of such class? The vote should be 2/3+1 surely as it is a language change.
> My motivation is to further expand class support to add modifiers (PPP - > public, protected, private). I added this change to initially segregate > grammar rules. It was an easy feature without extensive complexity and > covers some use-cases.
I'm not sure I understand this part. Could you explain more?
-- Stas Malyshev smalyshev@gmail.com

Lazare Inepologlou

11 years ago
2014-11-27 4:47 GMT+01:00 guilhermeblanco@gmail.com < guilhermeblanco@gmail.com>:
> Hi, > > I worked on an implementation of a somehow controversial concept that > exists in hack and C#: abstract final classes. > > https://wiki.php.net/rfc/abstract_final_class > > My motivation is to further expand class support to add modifiers (PPP - > public, protected, private). I added this change to initially segregate > grammar rules. It was an easy feature without extensive complexity and > covers some use-cases. > >
"Abstract final" is a strange way to name it. What you want is a "static" class: * The fact that one cannot initialise an abstract class is only a side effect. Abstract classes are meant to be used for inheritance. * Abstract static methods are not possible (one more reason why abstract is a bad name). * A "static" class does not have to be final, given the fact that PHP is one of the few languages that offer a robust Late Static Binding. Lazare INEPOLOGLOU Ingénieur Logiciel

Rowan Collins

11 years ago
Lazare Inepologlou wrote on 27/11/2014 10:35:
> 2014-11-27 4:47 GMT+01:00 guilhermeblanco@gmail.com < > guilhermeblanco@gmail.com>: > >> Hi, >> >> I worked on an implementation of a somehow controversial concept that >> exists in hack and C#: abstract final classes. >> >> https://wiki.php.net/rfc/abstract_final_class >> >> My motivation is to further expand class support to add modifiers (PPP - >> public, protected, private). I added this change to initially segregate >> grammar rules. It was an easy feature without extensive complexity and >> covers some use-cases. >> >> > "Abstract final" is a strange way to name it. What you want is a "static" > class: > > * The fact that one cannot initialise an abstract class is only a side > effect. Abstract classes are meant to be used for inheritance. > > * Abstract static methods are not possible (one more reason why abstract is > a bad name). > > * A "static" class does not have to be final, given the fact that PHP is > one of the few languages that offer a robust Late Static Binding.
This has always been my feeling. To me, "abstract" means "must be extended", and "final" means "can't be extended", so combining the two seems like a self-contradiction. The fact that abstract classes allow static methods to be called without sub-classing always seems a bit odd to me - it's as though only the constructor is really abstract, not the whole class. A "static" class, however, whether "final" or not, is definitely something I've wanted. Regards,
-- Rowan Collins [IMSoP]

Ferenc Kovacs

11 years ago
On Thu, Nov 27, 2014 at 1:43 PM, Rowan Collins <rowan.collins@gmail.com> wrote:
> Lazare Inepologlou wrote on 27/11/2014 10:35: > > 2014-11-27 4:47 GMT+01:00 guilhermeblanco@gmail.com < >> guilhermeblanco@gmail.com>: >> >> Hi, >>> >>> I worked on an implementation of a somehow controversial concept that >>> exists in hack and C#: abstract final classes. >>> >>> https://wiki.php.net/rfc/abstract_final_class >>> >>> My motivation is to further expand class support to add modifiers (PPP - >>> public, protected, private). I added this change to initially segregate >>> grammar rules. It was an easy feature without extensive complexity and >>> covers some use-cases. >>> >>> >>> "Abstract final" is a strange way to name it. What you want is a >> "static" >> class: >> >> * The fact that one cannot initialise an abstract class is only a side >> effect. Abstract classes are meant to be used for inheritance. >> >> * Abstract static methods are not possible (one more reason why abstract >> is >> a bad name). >> >> * A "static" class does not have to be final, given the fact that PHP is >> one of the few languages that offer a robust Late Static Binding. >> > > This has always been my feeling. To me, "abstract" means "must be > extended", and "final" means "can't be extended", so combining the two > seems like a self-contradiction. > > The fact that abstract classes allow static methods to be called without > sub-classing always seems a bit odd to me - it's as though only the > constructor is really abstract, not the whole class. > > A "static" class, however, whether "final" or not, is definitely something > I've wanted. > > Regards, > -- > Rowan Collins > [IMSoP] > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
for the record I also brought up this argument (abstract and final being contradicting ideas) in the pull request comments(before this thread was created).
-- Ferenc Kovács @Tyr43l - http://tyrael.hu

Sebastian Krebs

11 years ago
Hi, 2014-11-27 4:47 GMT+01:00 guilhermeblanco@gmail.com < guilhermeblanco@gmail.com>:
> Hi, > > I worked on an implementation of a somehow controversial concept that > exists in hack and C#: abstract final classes. > > https://wiki.php.net/rfc/abstract_final_class > >
The example is a little bit misleading: Instead of a new concept you can use functions, right? Regards, Sebastian
> My motivation is to further expand class support to add modifiers (PPP - > public, protected, private). I added this change to initially segregate > grammar rules. It was an easy feature without extensive complexity and > covers some use-cases. > > As a reference, here is the commit hash that added this feature to Hack: > > https://github.com/facebook/hhvm/commit/faedfaf46b0deb859b0c20fb36a574be7a4f2f55 > > Cheers, > > -- > Guilherme Blanco > MSN: guilhermeblanco@hotmail.com > GTalk: guilhermeblanco > Toronto - ON/Canada >
-- github.com/KingCrunch

Rowan Collins

11 years ago
guilhermeblanco@gmail.com wrote on 27/11/2014 03:47:
> I worked on an implementation of a somehow controversial concept that > exists in hack and C#: abstract final classes. > > https://wiki.php.net/rfc/abstract_final_class
The explanation of what exactly has been implemented could perhaps be expanded:
> Change language scanner to accept abstract final class constructor,
and subsequently restricting to only static members. Does this mean that the following will be flagged as invalid? If so, what error message will be raised? abstract final class Foo { abstract public function doTheImpossible(); } This class is technically valid as an abstract class, but the addition of the "final" keyword makes the abstract method declaration completely meaningless, since it can never be implemented. Regards,
-- Rowan Collins [IMSoP]

Guilherme Blanco

11 years ago
> In the RFC, I think one phrase needs clarification: > > Currently, PHP developers' only resource is to create a final class with > a private constructor, leading to untestable and error prone code. > > What is "error prone" in private __construct(); and how the RFC improves > the testability of such class?
The reason comes not to the construct method itself, but to other implemented methods. By forgetting "static" in any of your declared methods, you get no parse error and gives you 2 possibilities: - With E_STRICT enabled: Fatal error when non-static method is being statically called. You'll only get this at runtime, leading to potentially error prone. Now the testability come that with this addiction, you get a fatal error, which is easily fixable at compile time, not runtime. - With E_STRICT disabled: You get a warning on php log and everything works (which is a huge wtf mode).
> The vote should be 2/3+1 surely as it is a language change.
Sure, I can update the RFC to clarify this.
>> My motivation is to further expand class support to add modifiers (PPP - >> public, protected, private). I added this change to initially segregate >> grammar rules. It was an easy feature without extensive complexity and >> covers some use-cases. > > I'm not sure I understand this part. Could you explain more?
My end goal is to add class visibility to PHP. Unfortunately, I was forced to change bison grammar, reduce one ACC flag, so I could add this support. While doing that, I realized that "abstract final" was an easy support to add, since the entire engine already deals with both cases smoothly. All I had to do was remove the compiler check that was fataling and add necessary checks for class members. I stopped to code class visibility so we could vote on small incremental feature addictions. https://github.com/php/php-src/pull/911 is a requirement for class visibility too, because I'll move the ZEND_ACC_TRAIT to a proper binary value and address builtin_functions accordingly. I saw not linear room for a new flag, so I worked on reusing FINAL and now I worked on grammar support as part of this RFC's patch. Next patch will add PPP (public, protected, private) support to classes.
> "Abstract final" is a strange way to name it. What you want is a "static"
class:
> This has always been my feeling. To me, "abstract" means "must be
extended", and "final" means "can't be extended", so > combining the two seems like a self-contradiction.
> > The fact that abstract classes allow static methods to be called without
sub-classing always seems a bit odd to me - it's as > though only the constructor is really abstract, not the whole class.
> > A "static" class, however, whether "final" or not, is definitely
something I've wanted.
> for the record I also brought up this argument (abstract and final being > contradicting ideas) in the pull request comments(before this thread was > created).
No, because conceptually, a static something means that subsequent calls always return same value. A static class means a singleton, not what this patch proposal. You have to remember: - "abstract" means it cannot be instantiated directly - "final" means it cannot be extended
> The example is a little bit misleading: Instead of a new concept you can
use functions, right? Yes, but allowing namespace level functions does not give you property level functions.
> Does this mean that the following will be flagged as invalid? If so, what
error message will be raised?
> > abstract final class Foo { > abstract public function doTheImpossible(); > } > > This class is technically valid as an abstract class, but the addition of
the "final" keyword makes the abstract method
> declaration completely meaningless, since it can never be implemented.
You are correct. Methods cannot be declared abstract if you have an "abstract final". They must also be static. I added these checks together with static properties here: - Properties: https://github.com/php/php-src/pull/923/files#diff-3a8139128d4026ce0cb0c86beba4e6b9R4251 - Methods: https://github.com/php/php-src/pull/923/files#diff-3a8139128d4026ce0cb0c86beba4e6b9R3936 I'm able to expand the RFC in any way you may like before entering voting phase... just mention to me and I do it! =) Cheers, On Thu, Nov 27, 2014 at 8:14 AM, Rowan Collins <rowan.collins@gmail.com> wrote:
> guilhermeblanco@gmail.com wrote on 27/11/2014 03:47: > >> I worked on an implementation of a somehow controversial concept that >> exists in hack and C#: abstract final classes. >> >> https://wiki.php.net/rfc/abstract_final_class >> > > The explanation of what exactly has been implemented could perhaps be > expanded: > > > Change language scanner to accept abstract final class constructor, and > subsequently restricting to only static members. > > Does this mean that the following will be flagged as invalid? If so, what > error message will be raised? > > abstract final class Foo { > abstract public function doTheImpossible(); > } > > This class is technically valid as an abstract class, but the addition of > the "final" keyword makes the abstract method declaration completely > meaningless, since it can never be implemented. > > > Regards, > -- > Rowan Collins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Guilherme Blanco MSN: guilhermeblanco@hotmail.com GTalk: guilhermeblanco Toronto - ON/Canada

Rowan Collins

11 years ago
guilhermeblanco@gmail.com wrote on 27/11/2014 14:08:
> > In the RFC, I think one phrase needs clarification: > > > > Currently, PHP developers' only resource is to create a final class with > > a private constructor, leading to untestable and error prone code. > > > > What is "error prone" in private __construct(); and how the RFC improves > > the testability of such class? > > The reason comes not to the construct method itself, but to other > implemented methods. > By forgetting "static" in any of your declared methods, you get no > parse error and gives you 2 possibilities: > - With E_STRICT enabled: Fatal error when non-static method is being > statically called. You'll only get this at runtime, leading to > potentially error prone. Now the testability come that with this > addiction, you get a fatal error, which is easily fixable at compile > time, not runtime. > - With E_STRICT disabled: You get a warning on php log and everything > works (which is a huge wtf mode).
This is true of classes intended to be static whether or not they are final. Allowing a "static class" would allow you to enforce that all methods (and properties) must be static without banning users from extending it (which is a completely orthogonal decision).
> > "Abstract final" is a strange way to name it. What you want is a > "static" class: > > > This has always been my feeling. To me, "abstract" means "must be > extended", and "final" means "can't be extended", so > combining the > two seems like a self-contradiction. > > > > The fact that abstract classes allow static methods to be called > without sub-classing always seems a bit odd to me - it's as > though > only the constructor is really abstract, not the whole class. > > > > A "static" class, however, whether "final" or not, is definitely > something I've wanted. > > > for the record I also brought up this argument (abstract and final being > > contradicting ideas) in the pull request comments(before this thread was > > created). > > No, because conceptually, a static something means that subsequent > calls always return same value. A static class means a singleton, not > what this patch proposal. > You have to remember: > - "abstract" means it cannot be instantiated directly > - "final" means it cannot be extended
That's not how they're interpreted with regard to methods, unless I'm missing something: - "abstract function" means a method which must be implemented by a sub-class - "static function" means a method with no access to $this, operating outside of any instance Taking those behaviours for class definitions leads to the interpretation that seems natural to me: - "abstract class" means a class which must be extended before use, and may contain abstract methods - "static class" would mean a class which can never be used to create an instance, and can contain only static methods "final" is orthogonal to these, and means that a class cannot be extended; under this interpretation, "abstract final" is a contradiction, but "static final" makes perfect sense. Regards,
-- Rowan Collins [IMSoP]

Guilherme Blanco

11 years ago
> This is true of classes intended to be static whether or not they are
final. Allowing a "static class" would allow you to
> enforce that all methods (and properties) must be static without banning
users from extending it (which is a completely
> orthogonal decision).
So if I still want to not allow anyone to extend it, I would then have a final static class. Remember, I don't want people to change methods' visibility. How does that become different from final abstract? I know you answered below... =)
> That's not how they're interpreted with regard to methods, unless I'm
missing something:
> > - "abstract function" means a method which must be implemented by a
sub-class
> - "static function" means a method with no access to $this, operating
outside of any instance
> > Taking those behaviours for class definitions leads to the interpretation
that seems natural to me:
> > - "abstract class" means a class which must be extended before use, and
may contain abstract methods
> - "static class" would mean a class which can never be used to create an
instance, and can contain only static methods
> > "final" is orthogonal to these, and means that a class cannot be
extended; under this interpretation, "abstract final" is a
> contradiction, but "static final" makes perfect sense.
The piece it's missing in "static" definition: there can only be one instance of something. I'd argue that declaring a class static is the same as declaring a singleton. Multiple object instantiations over a static class would return always same instance. Now taking this into consideration, I'd modify your concepts to the following: - "abstract function" means a method which must be implemented by a sub-class - "static function" means a method with no access to $this, operating outside of any instance. This means it's bound to class entry, which can only have one possibility to be called: statically and given same parameters it should return same output, unless normal flow controlled by a static variable. I'm more than happy to change "abstract" to "static" if it's the desire of everybody. That would match C# implementation as defined here: http://msdn.microsoft.com/en-us/library/79b3xss3.aspx Now it's funny that C# also accepts "abstract final" with the same idea/concept of their documentation of static classes. #weird []s, On Thu, Nov 27, 2014 at 10:06 AM, Rowan Collins <rowan.collins@gmail.com> wrote:
> guilhermeblanco@gmail.com wrote on 27/11/2014 14:08: > >> > In the RFC, I think one phrase needs clarification: >> > >> > Currently, PHP developers' only resource is to create a final class with >> > a private constructor, leading to untestable and error prone code. >> > >> > What is "error prone" in private __construct(); and how the RFC improves >> > the testability of such class? >> >> The reason comes not to the construct method itself, but to other >> implemented methods. >> By forgetting "static" in any of your declared methods, you get no parse >> error and gives you 2 possibilities: >> - With E_STRICT enabled: Fatal error when non-static method is being >> statically called. You'll only get this at runtime, leading to potentially >> error prone. Now the testability come that with this addiction, you get a >> fatal error, which is easily fixable at compile time, not runtime. >> - With E_STRICT disabled: You get a warning on php log and everything >> works (which is a huge wtf mode). >> > > This is true of classes intended to be static whether or not they are > final. Allowing a "static class" would allow you to enforce that all > methods (and properties) must be static without banning users from > extending it (which is a completely orthogonal decision). > > > > "Abstract final" is a strange way to name it. What you want is a >> "static" class: >> >> > This has always been my feeling. To me, "abstract" means "must be >> extended", and "final" means "can't be extended", so > combining the two >> seems like a self-contradiction. >> > >> > The fact that abstract classes allow static methods to be called >> without sub-classing always seems a bit odd to me - it's as > though only >> the constructor is really abstract, not the whole class. >> > >> > A "static" class, however, whether "final" or not, is definitely >> something I've wanted. >> >> > for the record I also brought up this argument (abstract and final being >> > contradicting ideas) in the pull request comments(before this thread was >> > created). >> >> No, because conceptually, a static something means that subsequent calls >> always return same value. A static class means a singleton, not what this >> patch proposal. >> You have to remember: >> - "abstract" means it cannot be instantiated directly >> - "final" means it cannot be extended >> > > That's not how they're interpreted with regard to methods, unless I'm > missing something: > > - "abstract function" means a method which must be implemented by a > sub-class > - "static function" means a method with no access to $this, operating > outside of any instance > > Taking those behaviours for class definitions leads to the interpretation > that seems natural to me: > > - "abstract class" means a class which must be extended before use, and > may contain abstract methods > - "static class" would mean a class which can never be used to create an > instance, and can contain only static methods > > "final" is orthogonal to these, and means that a class cannot be extended; > under this interpretation, "abstract final" is a contradiction, but "static > final" makes perfect sense. > > > Regards, > -- > Rowan Collins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Guilherme Blanco MSN: guilhermeblanco@hotmail.com GTalk: guilhermeblanco Toronto - ON/Canada

Rowan Collins

11 years ago
guilhermeblanco@gmail.com wrote on 27/11/2014 15:34:
> > This is true of classes intended to be static whether or not they > are final. Allowing a "static class" would allow you to > > enforce that all methods (and properties) must be static without > banning users from extending it (which is a completely > > orthogonal decision). > > So if I still want to not allow anyone to extend it, I would then have > a final static class. Remember, I don't want people to change methods' > visibility.
Yep, that's the idea. I see no reason, particularly with Late Static Binding, that it shouldn't be possible to have a static class which can be extended by a static sub-class, if that fits a particular use case.

Guilherme Blanco

11 years ago
Ok... so if I update the RFC to be "static class", does that make everybody happy? I mainly wanna get this forward thinking trend... =) On Thu, Nov 27, 2014 at 10:49 AM, Rowan Collins <rowan.collins@gmail.com> wrote:
> guilhermeblanco@gmail.com wrote on 27/11/2014 15:34: > >> > This is true of classes intended to be static whether or not they are >> final. Allowing a "static class" would allow you to >> > enforce that all methods (and properties) must be static without >> banning users from extending it (which is a completely >> > orthogonal decision). >> >> So if I still want to not allow anyone to extend it, I would then have a >> final static class. Remember, I don't want people to change methods' >> visibility. >> > > Yep, that's the idea. I see no reason, particularly with Late Static > Binding, that it shouldn't be possible to have a static class which can be > extended by a static sub-class, if that fits a particular use case. > > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
-- Guilherme Blanco MSN: guilhermeblanco@hotmail.com GTalk: guilhermeblanco Toronto - ON/Canada

Stas Malyshev

11 years ago
Hi!
> By forgetting "static" in any of your declared methods, you get no parse > error and gives you 2 possibilities: > - With E_STRICT enabled: Fatal error when non-static method is being > statically called. You'll only get this at runtime, leading to potentially > error prone. Now the testability come that with this addiction, you get a > fatal error, which is easily fixable at compile time, not runtime.
I don't see how it matters for testability - sure, if you don't test your functions, you don't see the errors, but that's just best practice. Also, since PHP is not a compiled language, practical difference between "compile time" and "runtime" does not really exist.
> - With E_STRICT disabled: You get a warning on php log and everything works > (which is a huge wtf mode).
Not everything, your functions still do not. If you write a function and put it in production without ever trying to run it even once, that's something that needs to be fixed (and you could as well have made a typo in a function name or written whille() - there are a lot of errors that one can make and PHP does not catch, especially if you never run your code). Otherwise, the error is immediately obvious.
> My end goal is to add class visibility to PHP. Unfortunately, I was forced
I'm not sure how it is related, but if it's not directly connected then since that RFC does not exist AFAIK I don't think it can be an argument for this one. If it is directly connected then maybe it could wait for that RFC but then connection needs to be explained.
> No, because conceptually, a static something means that subsequent calls > always return same value. A static class means a singleton, not what this
I'm not sure where it comes from - static function definitely does not return same value on each call. Neither do static variables (which are just class variables, but not immutable) or static closures (which are just unbound closures). The only case where it is kind of true is static variable in function, if you replace "value" by "variable", but this is only because the syntax was borrowed from C. So static in PHP means a lot of thing but the general gist is "not subject to current scope". Where the "static class means a singleton" came from? Could you explain?
> You are correct. Methods cannot be declared abstract if you have an > "abstract final". They must also be static. I added these checks together
To me, it just feels a bit unnatural. So you have abstract class, which usually has abstract methods. Then you have "abstract final" class which can not have abstract methods, but instead should have "static" methods. This just sounds a bit weird to me - adding "final" to description of the class completely changes all the rules in very unexpected direction.
-- Stas Malyshev smalyshev@gmail.com

Josh Watzman

11 years ago
On Nov 27, 2014, at 10:34 PM, Stanislav Malyshev <smalyshev@gmail.com> wrote:
>> You are correct. Methods cannot be declared abstract if you have an >> "abstract final". They must also be static. I added these checks together > > To me, it just feels a bit unnatural. So you have abstract class, which > usually has abstract methods. Then you have "abstract final" class which > can not have abstract methods, but instead should have "static" methods. > This just sounds a bit weird to me - adding "final" to description of > the class completely changes all the rules in very unexpected direction.
What does it mean to have an abstract static function? Abstract (non-static) functions make sense for abstract classes -- since you cannot instantiate the abstract class, you know that the instantiable subclass that you actually have an instance of must have implemented the method, so it's safe to call. But you *can* call static methods on abstract classes, and so you have no guarantee that the abstract static method exists -- and you need to be very careful with LSB to actually call it correctly anyways. Does this mean that static classes with abstract methods (or abstract static classes, or however this ends up working out syntactically) won't be allowed to have static methods called on them directly? How do you make sure that the methods in them do the right LSB stuff to call the abstract static functions correctly? Inheritance semantics for static classes also get messy when you start dealing with traits. As a quick example, the current proposal only allows static classes to inherit from other static classes... but where do traits fit in here? Only traits with only static methods are allowed to be included? This could lead to some very annoying refactoring scenarios where changing a trait that is used in several places leads to errors with static classes... traits bring up many of the same issues as multiple inheritance, and I think you'll have some of those issues here. All of the above is the crux of the issue of why Hack went with "abstract final" and not anything else. Abstract does not mean "must be subclassed" -- you can have an abstract class with no subclasses and still call static methods on it; this is perfectly meaningful, and is at least how I emulated "abstract final" before Hack got the feature. Abstract means "cannot be instantiated" (and, since it cannot be instantiated, may contain *instance* methods with empty bodies, i.e., abstract methods). Then final means "cannot be subclassed" -- so the two together means you have a class that has no instances itself, and cannot be subclasses, so you can never have an object of that type. The use cases for being able to override such a class are questionable at best, as above. This really is just the combination of two existing class modifiers -- no need to introduce a new "static" modifier. And it leads to lots of interesting issues, as above. Josh Watzman