問題はJavaですが、なぜ抽象静的メソッドを定義できないのですか?例えば
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
問題はJavaですが、なぜ抽象静的メソッドを定義できないのですか?例えば
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
回答:
「抽象」は「機能を実装しない」という意味であり、「静的」は「オブジェクトインスタンスがなくても機能はある」という意味です。そして、それは論理的な矛盾です。
abstract static
は、完全に意味があります。サブクラスオブジェクトが実装する必要があるのは、クラスオブジェクト自体のメソッドです。もちろん、私が言葉にこだわっているにもかかわらず、物事の答え方は正しいです。
abstract static
:「サブクラスで実装される」関数X は同時に「クラスで実行される」ことができません - サブクラスでのみです。そのとき、それはもはや抽象的なものではありません。
static
「空ではない」という意味ではありません-これは、Javaが静的メソッドを抽象化できないことの結果です。「クラスで呼び出せる」という意味です。(「クラスでのみ呼び出し可能」を意味する必要がありますが、それは別の問題です。)Javaがサポートabstract static
するメソッドの場合、1)サブクラスで実装する必要があり、2)サブクラスのクラスメソッドであることを意味します。一部のメソッドは、インスタンスメソッドとしては意味がありません。残念ながら、Javaでは、抽象基本クラス(またはインターフェース)を作成するときにそれを指定できません。
言語のデザインが悪い。静的抽象メソッドを直接呼び出す方が、その抽象メソッドを使用するためだけにインスタンスを作成するよりもはるかに効果的です。特に、列挙型クラスを拡張できない場合の回避策として抽象クラスを使用する場合は、これは別の貧弱な設計例です。それらが次のリリースでそれらの制限を解決することを願っています。
static
それ自体の単なる概念はすでに違反であると言う人々がいます...
静的メソッドをオーバーライドすることはできないため、それを抽象化しても意味がありません。さらに、抽象クラスの静的メソッドは、オーバーライドするクラスではなく、そのクラスに属しているため、いずれにしても使用できませんでした。
abstract
メソッドへのアノテーションは、メソッドがサブクラスでオーバーライドされなければならないことを示しています。
Javaでは、static
メンバー(メソッドまたはフィールド)をサブクラスでオーバーライドすることはできません(これは他のオブジェクト指向言語では必ずしも当てはまりません。SmallTalkを参照してください)。static
メンバーは非表示になる場合がありますが、それはオーバーライドされたものとは根本的に異なります。
静的メンバーはサブクラスでオーバーライドできないため、abstract
アノテーションをそれらに適用することはできません。
余談ですが、他の言語はインスタンスの継承と同様に静的な継承をサポートしています。構文の観点から、これらの言語では通常、ステートメントにクラス名を含める必要があります。たとえば、Javaでは、ClassAでコードを記述している場合、これらは同等のステートメントです(methodA()が静的メソッドであり、同じシグネチャを持つインスタンスメソッドがない場合)。
ClassA.methodA();
そして
methodA();
SmallTalkでは、クラス名はオプションではないため、構文は次のとおりです(SmallTalkは。を使用して「主語」と「動詞」を区切るのではなく、statemendターミネーターとして使用します)。
ClassA methodA.
クラス名は常に必要であるため、クラス階層をたどることによって、メソッドの正しい「バージョン」を常に決定できます。それだけの価値があるので、私はときどきstatic
継承を見逃しており、最初にJavaを始めたとき、Javaに静的継承がないことに悩まされました。さらに、SmallTalkはダック型(したがって、契約ごとのプログラムはサポートされていません。)なのでabstract
、クラスメンバーの修飾子はありません。
私も同じ質問をしました、ここに理由があります
抽象クラスが言うので、それは実装を与えず、サブクラスがそれを与えることを可能にします
したがって、サブクラスはスーパークラスのメソッドをオーバーライドする必要があります。
RULE NO 1 - A静的メソッドがオーバーライドすることはできません
静的メンバーとメソッドはコンパイル時の要素であるため、静的メソッドのオーバーロード(コンパイル時ポリモーフィズム)は、オーバーライド(実行時ポリモーフィズム)ではなく許可されます。
したがって、それらは抽象的であってはなりません。
抽象staticのようなものはあり ません<--- Java Universeでは許可されていません
abstract static
参照すると確実に可能です。本当の理由 Javaは静的メソッドをオーバーライドすることはできませんので、Javaは静的メソッドをオーバーライドすることはできません理由です。
foo(String)
は同じではありませんfoo(Integer)
-それだけです。
これはひどい言語設計であり、それが不可能である理由については本当に理由はありません。
実際には、ここではそれがどのように実装されCANで行うことがJAVAは:
public class Main {
public static void main(String[] args) {
// This is done once in your application, usually at startup
Request.setRequest(new RequestImplementationOther());
Request.doSomething();
}
public static final class RequestImplementationDefault extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something AAAAAA");
}
}
public static final class RequestImplementaionOther extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something BBBBBB");
}
}
// Static methods in here can be overriden
public static abstract class Request {
abstract void doSomethingImpl();
// Static method
public static void doSomething() {
getRequest().doSomethingImpl();
}
private static Request request;
private static Request getRequest() {
// If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too.
if ( request == null ) {
return request = new RequestImplementationDefault();
}
return request;
}
public static Request setRequest(Request r){
return request = r;
}
}
}
=================以下の古い例=================
getRequestを探し、getRequestImpl ... setInstanceを呼び出して、呼び出しが行われる前に実装を変更できます。
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author Mo. Joseph
* @date 16 mar 2012
**/
public abstract class Core {
// ---------------------------------------------------------------
private static Core singleton;
private static Core getInstance() {
if ( singleton == null )
setInstance( new Core.CoreDefaultImpl() ); // See bottom for CoreDefaultImpl
return singleton;
}
public static void setInstance(Core core) {
Core.singleton = core;
}
// ---------------------------------------------------------------
// Static public method
public static HttpServletRequest getRequest() {
return getInstance().getRequestImpl();
}
// A new implementation would override this one and call setInstance above with that implementation instance
protected abstract HttpServletRequest getRequestImpl();
// ============================ CLASSES =================================
// ======================================================================
// == Two example implementations, to alter getRequest() call behaviour
// == getInstance() have to be called in all static methods for this to work
// == static method getRequest is altered through implementation of getRequestImpl
// ======================================================================
/** Static inner class CoreDefaultImpl */
public static class CoreDefaultImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
/** Static inner class CoreTestImpl : Alternative implementation */
public static class CoreTestImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return new MockedRequest();
}
}
}
次のように使用:
static {
Core.setSingleton(new Core.CoreDefaultImpl());
// Or
Core.setSingleton(new Core.CoreTestImpl());
// Later in the application you might use
Core.getRequest();
}
abstract static
質問で尋ねられた方法の例をどこに提供したか理解できず、太字でCAN JAVA BE DONE IN JAVAと書いてあります。これは完全に誤解です。
静的メソッドは、定義により、知る必要はありませんthis
。したがって、それは仮想メソッドになることはできません(それはthis
、を通じて利用可能な動的サブクラス情報に従ってオーバーロードされます)。代わりに、静的メソッドのオーバーロードは、コンパイル時に利用可能な情報のみに基づいています(つまり、スーパークラスの静的メソッドを参照すると、スーパークラスメソッドを呼び出しますが、サブクラスメソッドは呼び出しません)。
これによると、抽象静的メソッドは、その参照が定義済みの本体で置き換えられることがないため、まったく役に立たないでしょう。
私はすでに無数の答えがあることを知っていますが、実際的な解決策は見ていません。もちろん、これは実際の問題であり、Javaでこの構文を除外する理由はありません。元の質問には、これが必要になる可能性のあるコンテキストがないため、コンテキストと解決策の両方を提供します。
同一のクラスの束に静的メソッドがあるとします。これらのメソッドは、クラス固有の静的メソッドを呼び出します。
class C1 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C1
}
}
class C2 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C2
}
}
doWork()
メソッド内C1
とC2
同じです。これらの計算はたくさんある可能性があります:C3
C4
など。static abstract
許可されている場合は、次のようなことを行うことで重複したコードを排除します。
abstract class C {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
static abstract void doMoreWork(int k);
}
class C1 extends C {
private static void doMoreWork(int k) {
// code for class C1
}
}
class C2 extends C {
private static void doMoreWork(int k) {
// code for class C2
}
}
しかし、static abstract
組み合わせが許可されていないため、これはコンパイルされません。ただし、これstatic class
は許可されている構成で回避できます。
abstract class C {
void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
abstract void doMoreWork(int k);
}
class C1 {
private static final C c = new C(){
@Override void doMoreWork(int k) {
System.out.println("code for C1");
}
};
public static void doWork() {
c.doWork();
}
}
class C2 {
private static final C c = new C() {
@Override void doMoreWork(int k) {
System.out.println("code for C2");
}
};
public static void doWork() {
c.doWork();
}
}
このソリューションでは、複製される唯一のコードは
public static void doWork() {
c.doWork();
}
C1.doWork()
かC2.doWork()
、電話をかけることはできませんC.doWork()
。また、提供された例では機能しませんが、許可されている場合は、クラスはどのようにC
実装を見つけますdoMoreWork()
か?最後に、私はあなたのコンテキストコードを悪いデザインと呼びます。どうして?これは、一般的なコードの関数を作成してからクラスに静的関数を実装するのではなく、一意のコードの個別の関数を作成したからですC
。これは簡単です!!!
2つのクラスがあると仮定Parent
しChild
ます。Parent
ですabstract
。宣言は次のとおりです。
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
つまり、のインスタンスはParent
どのようrun()
に実行されるかを指定する必要があります。
しかし、今Parent
はそうではないと仮定しますabstract
。
class Parent {
static void run() {}
}
つまりParent.run()
、静的メソッドが実行されます。
abstract
メソッドの定義は「宣言されているが実装されていないメソッド」です。つまり、メソッド自体は何も返しません。
static
メソッドの定義は、「呼び出されたインスタンスに関係なく、同じパラメーターに同じ値を返すメソッド」です。
abstract
メソッドの戻り値は、インスタンスの変更として変更されます。static
方法はないでしょう。static abstract
この方法はかなりの戻り値が一定である方法であるが、何も返しません。これは論理的な矛盾です。
また、static abstract
メソッドには理由があまりありません。
抽象メソッドは、静的メソッドがその機能に静的にバインドされている間に動的バインディングを実現するために行われるため、静的メソッドを持つことはできません。静的メソッドは、インスタンス変数に依存しない動作を意味するため、インスタンス/オブジェクトは必要ありません。静的メソッドはオブジェクトではなくクラスに属します。それらは、PERMGENと呼ばれるメモリ領域に格納され、そこからすべてのオブジェクトと共有されます。抽象クラスのメソッドは、その機能に動的にバインドされます。
以下のような方法を宣言static
私たちはそのクラス名によってそのメソッドを呼び出すことができますし、そのクラスがある場合の手段abstract
としてだけでなく、それがすべてのボディが含まれていないとして、それを呼び出すために、したがって私たちは、両方のメソッドを宣言することはできません意味がないstatic
とabstract
。
静的メソッドは、クラスのインスタンスなしで呼び出すことができます。この例では、foo.bar2()を呼び出すことができますが、foo.bar()を呼び出すことはできません。barにはインスタンスが必要だからです。次のコードは機能します:
foo var = new ImplementsFoo();
var.bar();
静的メソッドを呼び出すと、常に同じコードで実行されます。上記の例では、bars2をImplementsFooで再定義しても、var.bar2()を呼び出すとfoo.bar2()が実行されます。
bar2に実装がない場合(これが抽象の意味です)、実装なしでメソッドを呼び出すことができます。それは非常に有害です。
インターフェイスのメソッド(親クラスの抽象メソッドのように機能する)を静的にできない理由という形で、この質問に対する答えを見つけたと思います。ここに完全な答えがあります(私のものではありません)
基本的に静的メソッドは、それらを呼び出すにはクラスを指定する必要があるため、コンパイル時にバインドできます。これはインスタンスメソッドとは異なり、メソッドの呼び出し元である参照のクラスはコンパイル時に不明になる可能性があります(したがって、呼び出されるコードブロックは実行時にのみ決定できます)。
静的メソッドを呼び出している場合は、それが実装されているクラス、またはその直接のサブクラスをすでに知っています。定義すると
abstract class Foo {
abstract static void bar();
}
class Foo2 {
@Override
static void bar() {}
}
次に、どのFoo.bar();
呼び出しも明らかに違法であり、常にを使用しますFoo2.bar();
。
これを念頭に置いて、静的抽象メソッドの唯一の目的は、サブクラスにそのようなメソッドを実装させることです。最初はこれは非常に間違っていると思うかもしれませんが、ジェネリック型パラメーターがある場合は、できる<E extends MySuperClass>
インターフェースを介して保証するとよいでしょう。型消去のため、ジェネリックはコンパイル時にのみ存在することに注意してください。E
.doSomething()
それで、それは役に立ちますか?はい、多分それがJava 8がインターフェースで静的メソッドを許可している理由です(ただし、デフォルトの実装でのみ)。クラスのデフォルト実装で静的メソッドを抽象化しないのはなぜですか?デフォルト実装の抽象メソッドが実際には具象メソッドだからです。
デフォルトの実装がない静的メソッドを抽象化/インターフェースしないのはなぜですか?どうやら、Javaがどのコードブロックを実行する必要があるかを識別する方法(単に私の答えの最初の部分)のためです。
抽象クラスはOOPSの概念であり、静的メンバーはOOPSの一部ではないので...
静的な完全なメソッドをインターフェイスで宣言でき、インターフェイス内でメインメソッドを宣言することでインターフェイスを実行できる
interface Demo
{
public static void main(String [] args) {
System.out.println("I am from interface");
}
}
抽象静的メソッドを持つという考えは、その特定の抽象クラスをそのメソッドに直接使用することはできないということですが、その静的メソッド(または総称:総称の実際のクラス)使用する)。
このようにして、たとえば、sortableObject抽象クラスを作成したり、(auto-)abstract静的メソッドとのインターフェースを作成したりして、ソートオプションのパラメーターを定義できます。
public interface SortableObject {
public [abstract] static String [] getSortableTypes();
public String getSortableValueByType(String type);
}
これで、これらのすべてのオブジェクトで同じである主なタイプでソートできるソート可能なオブジェクトを定義できます。
public class MyDataObject implements SortableObject {
final static String [] SORT_TYPES = {
"Name","Date of Birth"
}
static long newDataIndex = 0L ;
String fullName ;
String sortableDate ;
long dataIndex = -1L ;
public MyDataObject(String name, int year, int month, int day) {
if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
this.fullName = name ;
this.sortableDate = MyUtils.createSortableDate(year,month,day);
this.dataIndex = MyDataObject.newDataIndex++ ;
}
public String toString() {
return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
}
// override SortableObject
public static String [] getSortableTypes() { return SORT_TYPES ; }
public String getSortableValueByType(String type) {
int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
switch(index) {
case 0: return this.name ;
case 1: return this.sortableDate ;
}
return toString(); // in the order they were created when compared
}
}
これで、
public class SortableList<T extends SortableObject>
これは、タイプを取得し、ソートするタイプを選択するポップアップメニューを作成し、そのタイプからデータを取得することでリストを再ソートし、ソートタイプが選択されたときに自動で追加できる追加関数を持っています-新しいアイテムを並べ替えます。SortableListのインスタンスは "T"の静的メソッドに直接アクセスできることに注意してください。
String [] MenuItems = T.getSortableTypes();
インスタンスを使用する必要がある場合の問題は、SortableListにまだ項目がない可能性がありますが、優先される並べ替えを提供する必要があることです。
チェリオ、オラフ。
まず、抽象クラスの要点-抽象クラスはインスタンス化できません(wikiを参照)。だから、あなたが作成することはできません任意の抽象クラスのインスタンスを。
現在、Javaが静的メソッドを処理する方法は、そのクラスのすべてのインスタンスとメソッドを共有することです。
したがって、クラスをインスタンス化できない場合、抽象メソッドは拡張を要求するため、そのクラスは抽象静的メソッドを持つことができません。
ブーム。
Java docに従って:
静的メソッドは、オブジェクトではなく、それが定義されているクラスに関連付けられているメソッドです。クラスのすべてのインスタンスはその静的メソッドを共有します
Java 8では、デフォルトのメソッドとともに、静的メソッドもインターフェイスで許可されています。これにより、ライブラリでヘルパーメソッドを整理しやすくなります。インターフェースに固有の静的メソッドを、別のクラスではなく同じインターフェースに保持できます。
この良い例は:
list.sort(ordering);
の代わりに
Collections.sort(list, ordering);
静的メソッドを使用する別の例もドキュメント自体に記載されています。
public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
「抽象」はメソッドがオーバーライドされることを意味し、「静的」メソッドをオーバーライドすることはできないためです。
通常のメソッドは、サブクラスによってオーバーライドされ、機能が提供されることを意図している場合、抽象的です。クラスFoo
がBar1, Bar2, Bar3
etc によって拡張されていることを想像してください。したがって、それぞれのニーズに応じて、抽象クラスの独自のバージョンを持ちます。
これで、静的メソッドは定義によりクラスに属し、クラスのオブジェクトまたはそのサブクラスのオブジェクトとは何の関係もありません。それらは存在する必要さえなく、クラスをインスタンス化することなく使用できます。したがって、それらはすぐに使える必要があり、機能を追加するためにサブクラスに依存することはできません。
アブストラクトはアブストラクトメソッドに適用されるキーワードであるため、本文を指定しないでください。そして、静的キーワードについて話す場合、それはクラス領域に属しています。
これは、Java 8のインターフェースで実行できます。
これはそれに関する公式のドキュメントです:
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
クラスが抽象クラスを拡張する場合、抽象メソッドをオーバーライドする必要があり、それは必須であるためです。また、静的メソッドはコンパイル時に解決されるクラスメソッドであるため、オーバーライドされたメソッドは実行時に解決され、動的ポリモーフィズムに従うインスタンスメソッドです。