标签: abstract-base-class

抽象与接口 - 在Delphi中分离定义和实现

使用接口或抽象类分离定义和实现的更好方法是什么?

实际上我不喜欢将引用计数对象与其他对象混合.我想在保持大项目时这可能成为一场噩梦.

但有时我需要从2个或更多类/接口派生一个类.

你有什么经历?

delphi oop interface abstract-base-class

22
推荐指数
3
解决办法
4212
查看次数

Python抽象基类可以强制执行函数签名吗?

假设我定义了一个这样的抽象基类:

from abc import abstractmethod, ABCMeta

class Quacker(object):
  __metaclass__ = ABCMeta

  @abstractmethod
  def quack(self):
    return "Quack!"
Run Code Online (Sandbox Code Playgroud)

这确保了派生的任何类Quacker必须实现该quack方法.但是,如果我定义以下内容:

class PoliteDuck(Quacker):
   def quack(self, name):
     return "Quack quack %s!" % name

d = PoliteDuck()  # no error
Run Code Online (Sandbox Code Playgroud)

我被允许实例化该类,因为我提供了quack方法,但函数签名不匹配.我可以看到这在某些情况下可能有用,但我有兴趣确保我可以肯定地调用抽象方法.如果功能签名不同,这可能会失败!

那么:我如何强制执行匹配的函数签名?如果签名不匹配,我会期望在创建对象时出错,就像我根本没有定义它一样.

知道这不是惯用的,如果我想要这些类型的保证,那么Python是错误的语言,但这是不可能的 - 这是可能的吗?

python abstract-base-class

21
推荐指数
3
解决办法
4562
查看次数

如何让抽象数据类传递给mypy?

mypy v0.910 拒绝 Python 3.9 中的抽象数据类。这是最小的可重复示例:

from abc import ABC, abstractmethod
from dataclasses import dataclass

@dataclass
class Liquid(ABC):

    @abstractmethod
    def drip(self) -> None:
        pass
Run Code Online (Sandbox Code Playgroud)

这是错误消息:

$ mypy --python-version 3.9 so.py
so.py:4: error: Only concrete class can be given where "Type[Liquid]" is expected
Found 1 error in 1 file (checked 1 source file)
Run Code Online (Sandbox Code Playgroud)

如何让此代码通过mypy


笔记

我从mypy 问题 #5374中了解到,这是mypy中的一个错误,于 2018 年首次注意到,但仍未得到纠正。不过,我认为人们必须将mypy与抽象数据类一起使用,因此必须有一种解决方法或正确的方法来定义或注释该类。有什么推荐的?

错误消息的基础似乎是mypy假设任何类型的对象都Type可以实例化,但抽象类不能实例化。这似乎是错误,因为Type定义为表示类对象,而不一定是具体的类对象(即可以实例化的类对象)。

添加# type: ignore到包含的行 …

python abstract-base-class mypy python-dataclasses python-typing

16
推荐指数
2
解决办法
5552
查看次数

抽象基类与具体类作为超类

在阅读了最优秀的"Head First Design Patterns"一书之后,我开始向同事们传播模式和设计原则的好处.在颂扬我最喜欢的模式的优点 - 策略模式 - 我被问到一个让我停顿的问题.当然,策略使用继承和组合,当我的同事问"为什么使用抽象基类而不是具体的类?"时,我在其中一个关于"程序到接口(或超类型)而不是实现"的长篇大论. .
我只能提出"你强迫你的子类实现抽象方法并阻止它们实例化ABC".但说实话,这个问题让我想起了gaurd.

c# java architecture design-patterns abstract-base-class

12
推荐指数
2
解决办法
8545
查看次数

C++通过抽象基类在未知派生类上调用复制构造函数

我正在创建一个具有多种不同节点类型的树:二进制节点,一元节点和终端节点.我有一个所有节点继承的ABC.我正在尝试为树编写递归复制构造函数,如下所示:

class gpnode
{
public:
  gpnode() {};
  virtual ~gpnode() {};
  gpnode(const gpnode& src) {};

  gpnode* parent;
}

class bnode:gpnode
{
public:
  bnode() {//stuff};
  ~bnode() {//recursive delete};

  bnode(const bnode& src)
  {
    lnode = gpnode(src.lnode);
    rnode = gpnode(src.rnode);

    lnode->parent = this;
    rnode->parent = this;
  }

  gpnode* lnode;
  gpnode* rnode;
}

class unode:gpnode
{
public:
  unode() {//stuff};
  ~unode() {//recursive delete};

  unode(const unode& src)
  {
    node = gpnode(src.node);

    node->parent = this;
  }

  gpnode* node;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我做不到

node = gpnode(src.node);
Run Code Online (Sandbox Code Playgroud)

因为gpnode是一个虚拟类.我可以

node = unode(src.node);
Run Code Online (Sandbox Code Playgroud)

但是当unode的子节点是bnode时,这不起作用.如何让它智能地调用我需要它的复制构造函数?

c++ inheritance copy-constructor abstract-base-class

11
推荐指数
1
解决办法
4189
查看次数

基于抽象基类捕获异常

假设我有一个带有抽象基类的异常类,如下所示:

class MyExceptions(BaseExeption, metaclass=abc.ABCMeta):
    pass

class ProperSubclass(MyExceptions):
    pass

MyExceptions.register(ValueError)
Run Code Online (Sandbox Code Playgroud)

看来,我能赶上ProperSubclassMyExceptions,但不是ValueError:

try:
    raise ProperSubclass()
except MyExceptions:
    print('As expected, control comes here...')
except:
    print('...and not here.')

try:
    raise ValueError()
except MyExceptions:
    print('Control does not come here...')
except ValueError:
    print('...but unexpectedly comes here.')
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,我是否应该能够通过抽象基类捕获内置异常?如果是这样,怎么样?如果没有,那么规则是什么?

我想提出这个的另一种方式是:为匹配做,除非条款正确使用isinstance()/ issubclass(),如果没有(如出现这种情况)什么他们使用?也许在C实现中有一些阴暗的快捷方式.

python exception abstract-base-class

8
推荐指数
1
解决办法
2107
查看次数

Scala:Trait Mixin与抽象基类

我有一个抽象的基类(Base),它有一些为它定义的堆栈特征(StackingTrait).

trait Base {
  def foo
}
trait StackingTrait extends Base {
  abstract override def foo { super.foo }
}
Run Code Online (Sandbox Code Playgroud)

使用以下语法实现子类非常方便,但是这不起作用,因为编译器说foo需要声明,override然后abstract override重新编译,这是一个无效的因为Impl是一个类.

class Impl extends Base with StackingTrait {
  def foo {}
}
Run Code Online (Sandbox Code Playgroud)

我想不出为什么不允许这样的语法的一个很好的理由; foo在逻辑上被定义为Impl使得在概念上发生堆叠的顺序保持不变.

注意:我发现这种解决方法可以有效地完成我想要的相同操作,但是帮助类的必要性使我想要一个更好的解决方案.

class ImplHelper extends Base {
  def foo {}
}
class Impl extends ImplHelper with StackingTrait
Run Code Online (Sandbox Code Playgroud)

为什么没有编译所需的语法,是否有一个优雅的解决方案?

scala traits mixins abstract-base-class

7
推荐指数
1
解决办法
1804
查看次数

使用抽象基类VS普通继承

我试图了解使用抽象基类的好处.考虑这两段代码:

抽象基类:

from abc import ABCMeta, abstractmethod, abstractproperty

class CanFly:
    __metaclass__ = ABCMeta

    @abstractmethod
    def fly(self):
        pass

    @abstractproperty
    def speed(self):
        pass


class Bird(CanFly):

    def __init__(self):
        self.name = 'flappy'

    @property
    def speed(self):
        return 1

    def fly(self):
        print('fly')


b = Bird()

print(isinstance(b, CanFly))  # True
print(issubclass(Bird, CanFly))  #  True
Run Code Online (Sandbox Code Playgroud)

简单继承:

class CanFly(object):

    def fly(self):
        raise NotImplementedError

    @property
    def speed(self):
        raise NotImplementedError()


class Bird(CanFly):

    @property
    def speed(self):
        return 1

    def fly(self):
        print('fly')


b = Bird()

print(isinstance(b, CanFly))  # True
print(issubclass(Bird, CanFly)) …
Run Code Online (Sandbox Code Playgroud)

python abstract-base-class

7
推荐指数
1
解决办法
534
查看次数

初始化派生自和抽象的类时出现python错误

我有这个简单的代码,我得到一个奇怪的错误:

from abc import ABCMeta, abstractmethod

class CVIterator(ABCMeta):

    def __init__(self):

        self.n = None # the value of n is obtained in the fit method
        return


class KFold_new_version(CVIterator): # new version of KFold

    def __init__(self, k):
        assert k > 0, ValueError('cannot have k below 1')
        self.k = k
        return 


cv = KFold_new_version(10)

In [4]: ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-ec56652b1fdc> in <module>()
----> 1 __pyfile = open('''/tmp/py13196IBS''');exec(compile(__pyfile.read(), '''/home/donbeo/Desktop/prova.py''', 'exec'));__pyfile.close()

/home/donbeo/Desktop/prova.py in <module>()
     19 
     20 
---> 21 cv = KFold_new_version(10) …
Run Code Online (Sandbox Code Playgroud)

python inheritance abstract-base-class

6
推荐指数
1
解决办法
2516
查看次数

为什么 mypy 不理解这个对象实例化?

我正在尝试定义一个类,该类将另一个类作为属性_model并将实例化该类的对象。

from abc import ABC
from typing import Generic, TypeVar, Any, ClassVar, Type

Item = TypeVar("Item", bound=Any)


class SomeClass(Generic[Item], ABC):
    _model: ClassVar[Type[Item]]

    def _compose_item(self, **attrs: Any) -> Item:
        return self._model(**attrs)
Run Code Online (Sandbox Code Playgroud)

self._model(**attrs)我认为返回 , 的实例应该是显而易见的Item,因为_model被显式声明为Type[Item]并被attrs声明为Dict[str, Any]

但我从中得到的mypy 0.910是:

test.py: note: In member "_compose_item" of class "SomeClass":
test.py:11: error: Returning Any from function declared to return "Item"
            return self._model(**attrs)
            ^
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

python type-hinting abstract-base-class mypy python-typing

6
推荐指数
1
解决办法
547
查看次数