2016-05-19 6 views
0

実際の実装が各サブクラスで実装されるため、重要なことはわかりません。私はこの言葉を把握する難しさを持っていますので、私は今、何かが欠けする必要があります多型のため抽象クラスで実装されていないメソッドを持つ必要性?

class Cat: 
    def __init__(self, breed): 
     self.breed = breed 
    def sound(self): # having this or not does'nt make any difference 
     pass 

class Angora(Cat): 
    def sound(self): 
     print("miau") 

class Scotish(Cat): 
    def sound(self): 
     print('meowww') 

a = Angora('angora') 
b = Scotish('scotish') 

cats = [a, b] 

for catt in cats: 
    catt.sound() 

:このコードを考えてみましょう。

+1

'abc'モジュールをチェックすると、これをバリエーションとして使用して便利なエラーチェックができます。 –

答えて

1

が上書きされます空のメソッドを置く、ない多くのポイントが存在しませんが、Catは、実際の抽象クラスだったとsoundであった場合は、 上書きされるをinforcedた方法は、それからの大きな利点は、たとえば、そこにある:

import abc 

class Cat(abc.ABC): 
    def __init__(self, breed): 
     self.breed = breed 
    @abc.abstractmethod 
    def sound(self): # having this as an abstract method DOES make a difference 
     pass 

class Scotish(Cat): 
    def sonud(self): 
     print('meowww') 

Scotishを初期化しようとしたとき、あなたがタイプミスに気づいたかどうかは、あなたがこのエラーになります:

>>> b = Scotish("scotish") 
Traceback (most recent call last): 
    File "<pyshell#12>", line 1, in <module> 
    b = Scotish("scotish") 
TypeError: Can't instantiate abstract class Scotish with abstract methods sound 

奇妙なあいまいなエラーが発生する前に、実際に何が間違っているのかが分かります。

また、単純にraise NotImplementedErrorとは異なり、抽象メソッドには抽象的なコードも含まれています。関数がやるかもしれないものの例のように、偉大な例では、_collections_abc.Generator.throw次のようになります。

@abstractmethod 
def throw(self, typ, val=None, tb=None): 
    """Raise an exception in the coroutine. 
    Return next yielded value or raise StopIteration. 
    """ 
    if val is None: 
     if tb is None: 
      raise typ 
     val = typ() 
    if tb is not None: 
     val = val.with_traceback(tb) 
    raise val 

これは実際のコードではありません、これは発電機が実際にthrowメソッドを処理する方法はありませんが、それはの偉大抽象です議論を少なくとも処理する方法!

2

あなたはこのようなものが必要なので、どのサブクラスでもメソッドを実装するのを忘れた場合は例外が表示されます。

class Cat: 
    def __init__(self, breed): 
     self.breed = breed 

    def sound(self): 
     raise NotImplementedError('Should be implemented in subclass') 

また、クラスインタフェースをクリーナーにします。

+0

'Cat'が' sound'を持たない場合は、とにかく例外が発生します。それはあなたが使ったエラーほど有益な、 'AttributeError'です。 – user2357112

+0

@ user2357112 [私のシナリオが誤植](http://stackoverflow.com/a/37335195/5827215)を参照してください。その場合は、単にAttributeError: 'Scotish'オブジェクトには属性 'sound'がありません。タイプミスが見えない場合は本当に混乱します。サブクラスで適切にオーバーライドされていないことが具体的に伝えられると、少なくとも何が間違っているかが絞り込まれます。 –

+0

@ user2357112 'NotImplementedError'は、' AttributeError'と違って、何かを実装するのを忘れていると言います。 – dizballanze

1

コードを動作させる必要がない場合でも、コードを自己文書化すると、将来的にCatを実装するのが容易になります。また、Catオブジェクトに対してイントロスペクション/リフレクションを使用することもできます。 も参照してくださいここではPythonのために「適切な」抽象基底クラスを追加するための動機:https://www.python.org/dev/peps/pep-3119/

0

これまで言われていないもの:

これはopen closed principleのの点で音のソリューションを実装するための重要な要素です。

重要なポイントは:通常、特定の動作を実装するために抽象基本クラスを使用しています...すべてのサブクラスで同じである必要があります。一方、この「共通の」実装では、サブクラス固有のメソッドを呼び出す必要があるかもしれません。

いくつかの擬似コードの例:

その後
abstract class Base: 
    final foo(): 
     return "foo" + infoFromChild() 

    abstract infoFromChild() 

  • あなたは、「空の抽象を上書きすることができますベース
  • から継承する任意のオブジェクトの "FOOを()" を呼び出すことができinfoFromChildそれぞれの子どものクラスで適切なものへ

もちろん:そのようなものma JavaやC++のような "より静的な"言語では、 "センス"をはるかに上回ります。 Python内では、とにかく別のことをするかもしれません。

関連する問題