Javaの「抽象クラス」とは何ですか?
Javaの「抽象クラス」とは何ですか?
回答:
抽象クラスは、インスタンス化できないクラスです。抽象クラスは、インスタンス化できる継承サブクラスを作成することによって使用されます。抽象クラスは、継承するサブクラスに対していくつかのことを行います。
次に例を示します。
abstract public class AbstractClass
{
abstract public void abstractMethod();
public void implementedMethod() { System.out.print("implementedMethod()"); }
final public void finalMethod() { System.out.print("finalMethod()"); }
}
「abstractMethod()」にはメソッド本体がないことに注意してください。このため、次のことはできません。
public class ImplementingClass extends AbstractClass
{
// ERROR!
}
実装するメソッドはありませんabstractMethod()
!したがって、JVMがのようなものになったときに何をすべきかを知る方法はありませんnew ImplementingClass().abstractMethod()
。
ここに正しいImplementingClass
です。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
}
implementedMethod()
またはを定義する必要がないことに注意してくださいfinalMethod()
。それらはすでにによって定義されていAbstractClass
ます。
ここに別の正しいImplementingClass
です。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
この場合、を上書きしましたimplementedMethod()
。
ただし、final
キーワードのため、次のことはできません。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
public void finalMethod() { System.out.print("ERROR!"); }
}
finalMethod()
in の実装がAbstractClass
の最終実装としてマークされているため、これを行うことはできませんfinalMethod()
。他の実装は許可されません。
これで、抽象クラスを2回実装することもできます。
public class ImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("abstractMethod()"); }
public void implementedMethod() { System.out.print("Overridden!"); }
}
// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
public void abstractMethod() { System.out.print("second abstractMethod()"); }
}
これでどこかに別のメソッドを書くことができます。
public tryItOut()
{
ImplementingClass a = new ImplementingClass();
AbstractClass b = new ImplementingClass();
a.abstractMethod(); // prints "abstractMethod()"
a.implementedMethod(); // prints "Overridden!" <-- same
a.finalMethod(); // prints "finalMethod()"
b.abstractMethod(); // prints "abstractMethod()"
b.implementedMethod(); // prints "Overridden!" <-- same
b.finalMethod(); // prints "finalMethod()"
SecondImplementingClass c = new SecondImplementingClass();
AbstractClass d = new SecondImplementingClass();
c.abstractMethod(); // prints "second abstractMethod()"
c.implementedMethod(); // prints "implementedMethod()"
c.finalMethod(); // prints "finalMethod()"
d.abstractMethod(); // prints "second abstractMethod()"
d.implementedMethod(); // prints "implementedMethod()"
d.finalMethod(); // prints "finalMethod()"
}
タイプを宣言しb
たにもかかわらずAbstractClass
、が表示されることに注意してください"Overriden!"
。これは、インスタンス化したオブジェクトが実際にImplementingClass
はでimplementedMethod()
あり、もちろんオーバーライドされているためです。(これは多型と呼ばれているのを見たかもしれません。)
特定のサブクラスに固有のメンバーにアクセスする場合は、最初にそのサブクラスにキャストダウンする必要があります。
// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();
最後に、次のことはできません。
public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
... // implementation
}
一度に拡張できるクラスは1つだけです。複数のクラスを拡張する必要がある場合、それらはインターフェースでなければなりません。あなたはこれを行うことができます:
public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
... // implementation
}
以下はインターフェースの例です。
interface InterfaceA
{
void interfaceMethod();
}
これは基本的に次と同じです:
abstract public class InterfaceA
{
abstract public void interfaceMethod();
}
唯一の違いは、2番目の方法では、それが実際にインターフェースであることをコンパイラーに知らせないことです。これは、インターフェースを実装するだけで他のユーザーは実装しないようにする場合に役立ちます。ただし、一般的な初心者の経験則として、抽象クラスに抽象メソッドしかない場合は、おそらくそれをインターフェイスにする必要があります。
以下は違法です:
interface InterfaceB
{
void interfaceMethod() { System.out.print("ERROR!"); }
}
インターフェイスにメソッドを実装することはできません。つまり、2つの異なるインターフェースを実装する場合、それらのインターフェースの異なるメソッドは衝突できません。インターフェースのすべてのメソッドは抽象なので、メソッドを実装する必要があり、メソッドは継承ツリーの唯一の実装であるため、コンパイラーはメソッドを使用する必要があることを認識しています。
c.implementedMethod()
「Overriden!」と印刷するのですか?SecondImplementingClass
オーバーライドしませんimplementedMethod()
。
Javaクラスは、次の条件下で抽象になります。
1.少なくとも1つのメソッドが抽象としてマークされている:
public abstract void myMethod()
その場合、コンパイラーはクラス全体を抽象としてマークするように強制します。
2.クラスは抽象としてマークされます。
abstract class MyClass
すでに述べたように:抽象メソッドがある場合、コンパイラーはクラス全体を抽象としてマークするように強制します。ただし、抽象メソッドがない場合でも、クラスを抽象としてマークできます。
一般的な使用:
抽象クラスの一般的な用途は、インターフェースと同様に、クラスの概要を提供することです。ただし、インターフェイスとは異なり、すでに機能を提供できます。つまり、クラスの一部が実装され、一部はメソッド宣言で概説されているだけです。("概要")
抽象クラスはインスタンス化できませんが、抽象クラスに基づいて具象クラスを作成し、インスタンス化することができます。そのためには、抽象クラスから継承して、抽象メソッドをオーバーライドする、つまり実装する必要があります。
abstract
クラスが抽象的であるために必要なのはキーワードだけであることは暗に示されています。ただし、具象クラスにメソッドを含めることはできません。したがって、クラスにメソッドがある場合は、コンパイラーに対してクラスとして宣言する必要があります。abstract
abstract
abstract
abstractキーワードを使用して宣言されたクラスは、と呼ばれabstract class
ます。抽象化は、データ実装の詳細を隠し、機能のみをユーザーに表示するプロセスです。抽象化を使用すると、オブジェクトの動作ではなく、オブジェクトの動作に焦点を合わせることができます。
抽象クラスの主なもの
抽象クラスには、抽象メソッドが含まれる場合と含まれない場合があります。非抽象メソッドが存在する場合があります。
抽象メソッドは、次のように、実装なし(中括弧なし、セミコロンが続く)で宣言されたメソッドです。
例: abstract void moveTo(double deltaX, double deltaY);
クラスに少なくとも1つの抽象メソッドがある場合、そのクラスは抽象でなければなりません
抽象クラスがインスタンス化されていない可能性があります(抽象クラスのオブジェクトの作成は許可されていません)
抽象クラスを使用するには、それを別のクラスから継承する必要があります。その中のすべての抽象メソッドに実装を提供します。
抽象クラスを継承する場合は、その中のすべての抽象メソッドに実装を提供する必要があります。
抽象クラスの宣言宣言abstract
時にクラスの前にキーワードを
指定すると、抽象化されます。以下のコードを見てください:
abstract class AbstractDemo{ }
抽象メソッドの宣言宣言abstract
時にメソッドの前にキーワードを
指定すると、抽象メソッドになります。以下のコードを見てください、
abstract void moveTo();//no body
クラスを抽象化する必要がある理由
オブジェクト指向の描画アプリケーションでは、円、長方形、線、ベジェ曲線、およびその他の多くのグラフィックオブジェクトを描画できます。これらのオブジェクトはすべて、特定の状態(例-の場合:位置、方向、線の色、塗りつぶしの色)と動作(例-の場合:moveTo、回転、サイズ変更、描画)が共通しています。これらの状態と動作の一部は、すべてのグラフィックオブジェクトで同じです(例:塗りつぶしの色、位置、およびmoveTo)。その他は異なる実装が必要です(例:サイズ変更または描画)。すべてのグラフィックオブジェクトは、それ自体を描画またはサイズ変更できる必要があります。それらの方法が異なるだけです。
これは、抽象スーパークラスに最適な状況です。GraphicObject
次の図に示すように、類似点を利用して、同じ抽象親オブジェクト(ex:の場合)から継承するようにすべてのグラフィックオブジェクトを宣言できます。
最初に、抽象クラスを宣言しGraphicObject
て、現在の位置やmoveToメソッドなど、すべてのサブクラスで完全に共有されるメンバー変数とメソッドを提供します。GraphicObject
また、すべてのサブクラスで実装する必要があるが、さまざまな方法で実装する必要がある、drawまたはresizeなどの抽象メソッドも宣言しました。GraphicObject
クラスは、このような何かを見ることができます:
abstract class GraphicObject {
void moveTo(int x, int y) {
// Inside this method we have to change the position of the graphic
// object according to x,y
// This is the same in every GraphicObject. Then we can implement here.
}
abstract void draw(); // But every GraphicObject drawing case is
// unique, not common. Then we have to create that
// case inside each class. Then create these
// methods as abstract
abstract void resize();
}
サブクラスでの抽象メソッドの使用法およびGraphicObject
などのの非抽象サブクラスはそれぞれ、およびメソッドの実装を提供する必要があります。Circle
Rectangle
draw
resize
class Circle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
class Rectangle extends GraphicObject {
void draw() {
//Add to some implementation here
}
void resize() {
//Add to some implementation here
}
}
main
メソッド内では、次のようにすべてのメソッドを呼び出すことができます。
public static void main(String args[]){
GraphicObject c = new Circle();
c.draw();
c.resize();
c.moveTo(4,5);
}
Javaで抽象化を実現する方法
Javaで抽象化を実現するには2つの方法があります
コンストラクター、データメンバー、メソッドなどを含む抽象クラス
abstract class GraphicObject {
GraphicObject (){
System.out.println("GraphicObject is created");
}
void moveTo(int y, int x) {
System.out.println("Change position according to "+ x+ " and " + y);
}
abstract void draw();
}
class Circle extends GraphicObject {
void draw() {
System.out.println("Draw the Circle");
}
}
class TestAbstract {
public static void main(String args[]){
GraphicObject grObj = new Circle ();
grObj.draw();
grObj.moveTo(4,6);
}
}
出力:
GraphicObject is created
Draw the Circle
Change position according to 6 and 4
2つのルールを覚えておいてください。
クラスに抽象メソッドと具象メソッドがほとんどない場合は、クラスとして宣言しabstract
ます。
クラスに抽象メソッドしかない場合は、それをとして宣言しinterface
ます。
参照:
簡単に言えば、抽象クラスは、もう少し機能の多いインターフェースのようなものと考えることができます。
抽象クラスを保持するインターフェイスをインスタンス化することはできません。
あなたのインターフェイスでは、あなただけのメソッドヘッダを定義することができ、実装のすべてがされて強制的に実行するために、すべての それらのを。抽象クラスでは、メソッドヘッダーを定義することもできますが、ここで(インターフェイスの違いに対して)、メソッドの本体(通常はデフォルトの実装)を定義することもできます。さらに、他のクラスが(実装ではなく、したがって、子クラスごとに1 つだけの抽象クラスを持つこともできる)拡張クラスである場合、抽象メソッドを指定しない限り、抽象クラスのすべてのメソッドを実装する必要はありません(そのような場合、それはインターフェースのように機能し、メソッド本体を定義することはできません)。
public abstract class MyAbstractClass{
public abstract void DoSomething();
}
それ以外の場合、抽象クラスの通常のメソッドの場合、「継承者」は通常どおり、デフォルトの動作を使用するか、それをオーバーライドできます。
例:
public abstract class MyAbstractClass{
public int CalculateCost(int amount){
//do some default calculations
//this can be overriden by subclasses if needed
}
//this MUST be implemented by subclasses
public abstract void DoSomething();
}
オラクルのドキュメントから
抽象メソッドとクラス:
抽象クラスは、抽象として宣言されたクラスです。抽象メソッドが含まれる場合と含まれない場合があります。
抽象クラスはインスタンス化できませんが、サブクラス化できます
抽象メソッドは、次のように、実装なし(中括弧なし、セミコロンが続く)で宣言されたメソッドです。
abstract void moveTo(double deltaX, double deltaY);
クラスに抽象メソッドが含まれている場合、次のようにクラス自体を抽象として宣言する必要があります。
public abstract class GraphicObject {
// declare fields
// declare nonabstract methods
abstract void draw();
}
抽象クラスがサブクラス化されると、サブクラスは通常、親クラスのすべての抽象メソッドの実装を提供します。ただし、そうでない場合は、サブクラスもabstractとして宣言する必要があります。
以来abstract classes
とinterfaces
関連している、SEの質問以下を見て:
ここで答えを入手してください:
ところで-それらはあなたが最近尋ねた質問です。評判を築くための新しい質問について考えてください...
編集:
この投稿者と参照された質問の投稿者の名前は同じか、少なくとも似ていますが、ユーザーIDは常に異なることに気づきました。したがって、技術的な問題があり、keyurが再度ログインして質問への回答を見つけるのに問題があるか、またはこれはSOコミュニティを楽しませるゲームの一種です;)
抽象クラスは直接インスタンス化することはできませんが、使用できるようにから派生する必要があります。抽象メソッドが含まれている場合、クラスは抽象でなければなりません:直接
abstract class Foo {
abstract void someMethod();
}
または間接的に
interface IFoo {
void someMethod();
}
abstract class Foo2 implements IFoo {
}
ただし、クラスは抽象メソッドを含まずに抽象クラスにすることができます。直接のインスタンス化を防ぐためのその方法、例えば
abstract class Foo3 {
}
class Bar extends Foo3 {
}
Foo3 myVar = new Foo3(); // illegal! class is abstract
Foo3 myVar = new Bar(); // allowed!
後者の抽象クラスのスタイルは、「インターフェースのような」クラスを作成するために使用できます。インターフェイスとは異なり、抽象クラスには非抽象メソッドとインスタンス変数を含めることができます。これを使用して、クラスを拡張するための基本機能を提供できます。
もう1つの頻繁なパターンは、抽象クラスに主要な機能を実装し、拡張クラスによって実装される抽象メソッドにアルゴリズムの一部を定義することです。愚かな例:
abstract class Processor {
protected abstract int[] filterInput(int[] unfiltered);
public int process(int[] values) {
int[] filtered = filterInput(values);
// do something with filtered input
}
}
class EvenValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove odd numbers
}
}
class OddValues extends Processor {
protected int[] filterInput(int[] unfiltered) {
// remove even numbers
}
}
public abstract class Place {
String Name;
String Postcode;
String County;
String Area;
Place () {
}
public static Place make(String Incoming) {
if (Incoming.length() < 61) return (null);
String Name = (Incoming.substring(4,26)).trim();
String County = (Incoming.substring(27,48)).trim();
String Postcode = (Incoming.substring(48,61)).trim();
String Area = (Incoming.substring(61)).trim();
Place created;
if (Name.equalsIgnoreCase(Area)) {
created = new Area(Area,County,Postcode);
} else {
created = new District(Name,County,Postcode,Area);
}
return (created);
}
public String getName() {
return (Name);
}
public String getPostcode() {
return (Postcode);
}
public String getCounty() {
return (County);
}
public abstract String getArea();
}
抽象クラスは、抽象として宣言されたクラスであり、抽象メソッドを含む場合と含まない場合があります。抽象クラスはインスタンス化できませんが、サブクラス化できます。
つまり、抽象キーワードで宣言されたクラスは、Javaでは抽象クラスと呼ばれます。抽象メソッド(ボディのないメソッド)と非抽象メソッド(ボディのあるメソッド)を持つことができます。
重要な注意:- 抽象クラスを使用してオブジェクトをインスタンス化することはできません。実行時のポリモーフィズムに対するJavaのアプローチはスーパークラス参照を使用して実装されるため、オブジェクト参照を作成するために使用できます。したがって、サブクラスオブジェクトを指すために使用できるように、抽象クラスへの参照を作成できる必要があります。以下の例でこの機能を確認できます
abstract class Bike{
abstract void run();
}
class Honda4 extends Bike{
void run(){
System.out.println("running safely..");
}
public static void main(String args[]){
Bike obj = new Honda4();
obj.run();
}
}
抽象クラスは完全には実装されていませんが、サブクラスの青写真のようなものを提供します。完全に定義された具象メソッドを含むという点で部分的に実装される場合がありますが、抽象メソッドを保持することもできます。これらは、シグネチャはあるがメソッド本体はないメソッドです。サブクラスでは、抽象メソッドごとに本体を定義する必要があります。それ以外の場合も、抽象クラスとして宣言する必要があります。抽象クラスはインスタンス化できないため、使用するには少なくとも1つのサブクラスで拡張する必要があります。抽象クラスを汎用クラスと考えてください。欠落している情報を埋めるためにサブクラスがあります。
それは何もせず、サブクラスのために共有される共通のテンプレートを提供するだけです