I have the following code in PyCharm:
from abc import ABC, abstractmethod
class Parent(ABC):
@abstractmethod
def foo(self, a):
raise NotImplementedError
class Child(Parent):
@staticmethod
def foo(a):
print(a)
class OtherChild(Parent):
@staticmethod
def foo(a, b=2):
print(a, b)
class ThirdChild(Parent):
def foo(self, a):
print(self, a)
Pycharm gives me a warning for "Signature of method 'Child.foo()' does not match signature of the base method in class 'Parent'". But see no such warnings on OtherChild.foo() or ThirdChild.foo().
I'm tyring to understand if I am see false positive or false negative warnings for signature matching.
I think that all three children are complian with the Liskov substitution principle because Parent.foo() has one required argument and each child method also has one required argument. I don't know if instance vs static method has any implications for Liskov substituion.
Basically I see two strange things here.
- If you compare
Child.foo()andOtherChild.foo()you can see they are both static methods (whereasParent.foo()is an instance method).Child.foo()gets the warning butOtherChild.foo()does not. Somehow adding the extra optional argument clears the signature matching warning. (adding a second required argument brings back the signature warning as I would expect based on LSP). - Now, if you compare
Child.foo()withThirdChild.foo()we see they are both methods with one required argument,abutChild.foo()is static whereasThirdChild.foo()is an instance method.ThirdChild.foo()does not get the warning.
So my questions are:
- Are all three of these classes indeed compliant with Liskov Substitution Principle? If not, why?
- Why do I only see the warning on
Child.foo()? Is this expected behavior or is this actually a PyCharm bug that I should report in their bug tracking system?
One workaround is I can do
class Child(Parent):
def foo(self, a):
print(a)
This is the same as the code above but I've left off the @staticmethod decorator around foo(). Normally this would give a Method 'foo' may be static warning, but in this case, I guess because the method is overriding a parent method, the warning is not present. This code gives no warnings.