如何修改一组兄弟类中相同的方法?

huangapple go评论69阅读模式
英文:

How to modify the same method in a set of sibling classes?

问题

我有两个类Table 和 Button继承自同一个类 Widget两个子类都有它们自己的 keyEvent() 方法并在必要时调用 Widget.keyEvent()我想以相同的方式修改两个类的 keyEvent() 行为例如使 `A``D` 键触发 `LEFT``RIGHT`)。

这段代码正如我所想

```python
class KeyModifier:
    def keyEvent():
        # 一些代码行
        super().keyEvent()

class MyTable(KeyModifier,Table):
    pass

class MyButton(KeyModifier,Button):
    pass

但 Pylance 生气了,因为 KeyModifier.super() 没有任何 keyEvent() 方法(这是正确的)。

有没有更好的方法?另外,我希望在将 KeyModifier 与未继承自 Widget 的东西一起使用时,Pylance 能提醒我。

这个示例来自一个 PyQT 应用程序,但问题更为一般。

编辑:
将 KeyModifier 设为 Widget 的子类会导致 KeyModifier.super().keyEvent() 调用 Widget.keyEvent(),而我想调用子类方法(Table.keyEvent() 或 Button.keyEvent())。


<details>
<summary>英文:</summary>

I have two classes (Table and Button) inherited from the same class Widget. Both subclasses have their own keyEvent() methods and both call Widget.keyEvent() when necessary. I want to modify the keyEvent() behaviour for both classes in the same way (for example make `A` and `D` keys to trigger `LEFT` and `RIGHT` keys).

This code works exactly as I want

```python
class KeyModifier:
    def keyEvent():
        # some lines of code
        super().keyEvent()

class MyTable(KeyModifier,Table):
    pass

class MyButton(KeyModifier,Button):
    pass

But Pylance is angry because KeyModifier.super() doesn't have any keyEvent() method (which is true).

Is there a way to do it better? Also, I would like Pylance to warn me when using the KeyModifier with something not inherited from Widget.

This example comes from a PyQT app, but the question is more general.

Edit:
Making KeyModifier a subclasss of Widget makes KeyModifier.super().keyEvent() call Widget.keyEvent() and I want to call the child class method (Table.keyEvent() or Button.keyEvent())

答案1

得分: 1

这有帮助吗?

英文:

Does it help?

from abc import abstractmethod


class Table:
    pass


class Button:
    pass


class KeyModifier:
    @abstractmethod
    def custom_operation(self):
        pass

    def key_event(self, condition):
        if condition:
            self.custom_operation()


class MyTable(KeyModifier, Table):
    def __init__(self):
        super(MyTable, self).__init__()

    def custom_operation(self):
        pass


class MyButton(KeyModifier, Button):
    def custom_operation(self):
        pass

答案2

得分: 0

如果你让KeyModifier继承自Widget,警告将会消失,因为keyEvent将会为该对象实际定义。如果你还在修改后的类中添加super().keyEvent()调用,所有合适的事件将会触发,这要归功于一种叫做MRO(Method Resolution Order)的东西。

class Base:
    def event(self):
        print("Base")

class A(Base):
    def event(self):
        print("A")

class B(Base):
    def event(self):
        print("B")

class Modifier(Base):
    def event(self):
        print("Modified")
        super().event()

class ModifiedA(Modifier, A):
    def event(self):
        print("ModifiedA")
        super().event()

class ModifiedB(Modifier, B):
    def event(self):
        print("ModifiedB")
        super().event()

ModifiedA().event()

输出结果:

ModifiedA
Modified
A

需要注意的是,如果AB不在它们自己的event方法中调用super(我相当肯定PyQt小部件会调用它们的父类方法),那么Modifier必须是第一个继承的类,因为这将导致它在MRO中首先出现,从而有机会调用其他类的方法。

英文:

If you make KeyModifier inherit from Widget, the warning will be gone because keyEvent will actually be defined for the object. If you also add super().keyEvent() calls to your modified classes, all the proper events will fire thanks to something called MRO - Method Resolution Order.

class Base:
    def event(self):
        print(&quot;Base&quot;)

class A(Base):
    def event(self):
        print(&quot;A&quot;)

class B(Base):
    def event(self):
        print(&quot;B&quot;)

class Modifier(Base):
    def event(self):
        print(&quot;Modified&quot;)
        super().event()

class ModifiedA(Modifier, A):
    def event(self):
        print(&quot;ModifiedA&quot;)
        super().event()

class ModifiedB(Modifier, B):
    def event(self):
        print(&quot;ModifiedB&quot;)
        super().event()

ModifiedA().event()

Output:

ModifiedA
Modified
A

It is important to note that if A and B do not call a super on their own (I'm fairly certain that PyQt widgets DO call their parent though), Modifier has to be the first class inherited, as it will cause it to be first in MRO and have a chance to call the other class method in turn.

答案3

得分: 0

I've found a workaround as I don't really have to manage any class methods but the event that is being handled.

def KeyModifier(event: Event) -> Event:
    # some lines of code and edit 'event' if necessary
    return event

class MyButton(Button):
    def keyEvent(self, event: Event):
        super().keyEvent(KeyModifier(event))

我找到了一个解决方法,因为我实际上不需要管理任何类方法,只需要处理事件。

def KeyModifier(event: Event) -> Event:
    # 一些代码行,根据需要编辑 'event'
    return event

class MyButton(Button):
    def keyEvent(self, event: Event):
        super().keyEvent(KeyModifier(event))

我认为这是最简单的编写方式。谢谢大家的建议 如何修改一组兄弟类中相同的方法?

英文:

I've found a workaround as I don't really have to manage any class methods but the event that is being handled.

def KeyModifier(event: Event) -&gt; Event:
    # some lines of code and edit &#39;event&#39; if necessary
    return event

class MyButton(Button):
    def keyEvent(self, event: Event):
        super().keyEvent(KeyModifier(event))

I think this is the simplest way to write it. Thank you all for your suggestions 如何修改一组兄弟类中相同的方法?

huangapple
  • 本文由 发表于 2023年2月6日 20:19:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75361242.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定