2011-02-10 10 views
0

抽象スーパークラスを作成した後、最初の具象サブクラスに到達すると、それらのメソッドのいくつかがその具体的なクラスで使用されなくても、すべての抽象メソッドを実装する必要があります。そう!あなたの具体的なサブクラスを取得するとき、あなたの1が0未満になることはありませんので、それは、何もしない空の具象メソッドを代わりに使用することができるのであれば、抽象メソッドを具体的なサブクラスで実装することをなぜ強制しますか?

public void doThis() { 
    if (1 < 0){ 
      int x = 34 
    } 
} 

そして、なぜ抽象スーパークラスには同じように、「偽」の方法にそれらの抽象メソッドを作成しません。これらすべての抽象メソッドを実装する必要はありませんが、あなたが実装したいもののためにあなたはちょうどあなたがそれをする必要がメソッドに書き換えることができます。

public void doThis() { 
     //does "this". 
} 

どちらの方法は右、多型を可能にしますか?では、抽象メソッドの本当のメリットは何ですか?

ありがとうございます!

+0

Btw、C++やJavaについて話していますか?私が考える限り、Javaでは、インタフェースは抽象基本クラスよりも常に優れた設計です。 – Falmarri

+3

@falmarri、私は同意しない、彼らは完全に異なっている。それらを一緒に使用できることに注意してください。インタフェースは振る舞いを定義するためのもので、抽象クラスは*いくつかの機能を提供するためのものですが、後で最後の詳細を埋め込むことができます。 – hvgotcodes

答えて

2

アイデアは、あなたが抽象クラスを使用することをポリシーを強制することです:

a)は抽象的ですクラスは

Bをインスタンス化することはできません)あなたはどのようにするための「空白を埋める」しなければなりません抽象的なものが行われます。つまり、抽象的なものをコンクリートにする必要があります。

これらのものは必要ありませんが、設計意図を明確にし、きれいにします。エラーを減らします。もし私たちがあなたのアプローチに従うならば、「ルール」が守られていることを確認するコンパイル時間チェックはありません。

javascriptのような多くの言語には「抽象的な」という概念はなく、人々はまだjavascriptで良いソフトウェアを書いています。

0

最初の場所で抽象メソッドが必要な理由によって異なります。たとえば、Template Methodデザインパターンでは、抽象メソッドで値を返す必要があります。明らかに、コンパイラは返す値を推測できません。

4

抽象基本クラスのメソッドをすべて実装していない場合は、デザインに問題があります。

+0

抽象クラスのすべてのメソッドがオーバーライドされるように設計されているわけではありません。 – chahuistle

2

抽象メソッドは、サブクラスを部分的に実装するエラーからあなたを保護します。基本メソッドが具体的で空白の場合、コンパイラはいくつかの仮想を再実装することができますが、他のものは再実装できません。

これが望ましい結果である場合があります。しかし、典型的にそうではありません。

1

考えていないことがいくつかあります。抽象クラスと抽象メソッドがあります。抽象クラスは直接インスタンス化することはできません。つまり、テンプレートだけです。抽象メソッドはabstracクラスでのみ定義でき、は空の(つまりボディなし)である必要がありますが、すべてを知っています。ただし、抽象クラスは非抽象メソッドを提供できます。完璧な例は、Log4jのAppenderSkeletonです(http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/AppenderSkeleton.htmlを参照)。

は抽象クラスです。継承する場合(あなたのクラスも抽象クラスでない限り)実装する必要がある抽象メソッド(append)と、それが必要なインターフェイスであるAppenderの2つのメソッドがあります。またはが子クラス(closeおよびrequireLayout)に抽象として渡されたを渡した。あなたは、たとえば、いくつかのものをツイートする独自のアペンダを書きたい場合は

さて、あなたが開始することにより:

public class TweetAppender extends AppenderSkeleton { 

    public boolean requiresLayout() { 
     return false; 
    } 

    public void close() { 
     // do nothing   
    } 

    @Override 
    protected void append(LoggingEvent event) { 
     // take the message and tweet it! 
    }  
} 

ので、伐採に関する複雑さのすべて(のレベルを設定し、フィルタを使用して、エラーハンドラー)はあなたから離れています。実際のロギングを行うだけで、残りの部分をlog4jが処理します。もちろん、あなたが望むなら、TweetAppenderは他のメソッドを上書きすることができます。おそらく、特別なエラー処理をしたいと思うかもしれません。この場合は、setErrorHandlerを上書きする必要があるかもしれません。

Facebook用のアペンダーとSkype上のステータスを変更するアペンダーを実装したいと考えているとします。状況の更新や変更などを投稿するために、Webサービスを介してAPIを公開しているとします。まもなく、Webサービスの呼び出しなど、似たようなことがいくつかあることに気付きます。また、Skypeには何らかのフォーマットがあることに気付きましたが、Tweeterにはもう1つのフォーマットがあります。だから、賢明アップあなたとWebServiceAppenderします

public abstract class WebServiceAppender extends AppenderSkeleton { 
    public boolean requiresLayout() { 
     return false; 
    } 

    public final void close() { 
     // do extra clean up of resources 
    } 

    // make this final so no one can do strange stuff 
    protected final void append(LoggingEvent event) { 
     // do a lot of stuff, like, opening up a connection 
     // send an xml, close the connection and stuff... 
     // ... 
     // ready to send the message! 
     final String messageToSend = getFormattedMessage(event); 
     // send the message and do lots of complicated stuff 
     // ... 
     // close and clean up 
    } 

    // let the implementations decide on the format 
    protected abstract String getFormattedMessage(LoggingEvent event); 
} 

、あなたのTweetAppenderは抽象としてgetFormattedMessageを宣言することにより

public class TweetAppender extends WebServiceAppender { 
    @Override 
    protected String getFormattedMessage(LoggingEvent event) { 
     // use tweeter's specific format 
    } 

    public boolean requiresLayout() { 
     return super.requiresLayout(); 
    } 
} 

ようになり、WebServiceAppenderは実際にかかる実装を提供するために、任意の実装を強制されますLoggingEventを返し、Stringを返します。また、appendcloseメソッドをfinalと宣言することにより、WebServiceAppenderはこれらのメソッドをオーバーライドすることを禁止しています。 requireLayoutメソッドはまだオーバーライドされています。

抽象クラスを継承するクラスの別のクールな機能は、superの使用です。親クラス 'thisと考えることができます。 TweetAppenderの場合には、requiresLayoutメソッドの実装は、このアペンダは、単に親クラスを使用してレイアウトを必要とするかどう基本的に決定するの責任を延期することを決定します。

だから、一緒にすべてを置く:

public class YourParentClass { 
    public void doThis() { 
     if (1 < 0){ 
      int x = 34 
    } 
} 

public class YourChildClass extends YourParentClass { 
    @Override 
    public void doThis() { 
     // do I want to do this, or something else? 
     if (iGuessIWillDoThis) { 
      super.doThis(); 
     } else { 
      // do something else 
     } 
    } 
} 

とにかく、私の2セントを。

関連する問題