静的メソッドが静的データのみを使用できるのはなぜですか?


38

静的メソッドが非静的データを使用できない理由がわかりません。誰が問題が何であり、なぜそれができないのかを説明できますか?


11
静的メソッドの観点からは静的データのみが存在するためです。
ムーヴィシエル

4
あなたの研究を共有することは誰にとっても役立ちます。試したことと、それがニーズに合わなかった理由を教えてください。これは、あなたが時間をかけて自分自身を助けようとしていること、明白な答えを繰り返すことから私たちを救うこと、そして何よりもあなたがより具体的で関連性のある答えを得ることを助けることを示しています。質問方法
-gnat

19
この場合、@ gnat OPは設計決定の背後にある理由を理解しようとしています。この場合、彼は何を試みると期待していますか?
オタク

2
@Geek-静的メソッドの存在、静的データは言語設計の問題です。標準的な意味を仮定すると、静的メソッドがインスタンスデータにアクセスできないという事実はそうではありません。制限は、一部の言語設計者の脆弱性ではなく、定義と可能なことによって意味をなします。
Steve314

6
ガートルード・スタインの言い換えには:「何もありません。この存在。」
カバダンサー

回答:


73

ほとんどのオブジェクト指向言語では、クラス内でメソッドを定義すると、インスタンスメソッドになります。キーワードを使用してそのクラスの新しいインスタンスを作成すると、newそのインスタンスに固有の新しいデータセットが初期化されます。そのインスタンスに属するメソッドは、そのインスタンスで定義したデータを処理できます。

対照的に、静的メソッドは個々のクラスインスタンスを認識しません。静的メソッドは、CまたはC ++のフリー関数に似ています。クラスの特定のインスタンス化に関連付けられていません。これが、インスタンス値にアクセスできない理由です。値を取得するインスタンスはありません!

静的データは静的メソッドに似ています。宣言された値にはstaticインスタンスが関連付けられていません。インスタンスごとに存在し、メモリ内の1か所でのみ宣言されます。変更された場合、そのクラスのすべてのインスタンスで変更されます。

A 静的メソッドにアクセスすることができます静的データを彼らは両方のクラスの特定のインスタンスとは独立して存在しているため。

インスタンスメソッドと比較して、静的メソッドを呼び出す方法を確認すると役立つ場合があります。次のクラスがあったとしましょう(Javaのような擬似コードを使用):

class Foo {
    // This static value belongs to the class Foo
    public static final string name = "Foo";

    // This non-static value will be unique for every instance
    private int value;

    public Foo(int value) {
         this.value = value;
    }

    public void sayValue() {
        println("Instance Value: " + value);
    }

    public static void sayName() {
        println("Static Value: " + name);
    }
}

Foo foo1 = new Foo(10);
Foo foo2 = new Foo(20);

foo1.sayValue(); // Prints "Instance Value: 10" - called on foo1
foo2.sayValue(); // Prints "Instance Value: 20" - called on foo2

Foo.sayName(); // Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)

更新

などから来るコメントで指摘して、静的な方法がある非静的データを扱うことのできる、それが明示的に渡さなければなりません。Fooクラスに別のメソッドがあると仮定しましょう:

public static Foo Add(Foo foo1, Foo foo2) {
    return new Foo(foo1.value + foo2.value);
}

Addまだ静的でありvalue、独自のインスタンスはありませんが、Fooクラスのメンバーであるためvalue、渡されたインスタンスfoo1およびfoo2インスタンスのプライベートフィールドにアクセスできます。この場合、両方の渡された値の追加された値で新しい を返すためにそれを使用していFooます。

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30

30
上の拡張「から値を取るために何のインスタンスはありません」 -インスタンスがある場合でも、静的メソッドを知ることができないこれからの値を取るようにインスタンス。
Steve314

9
これは、デフォルトですべてをオブジェクトの一部にすることを強制しない言語で説明するのがはるかに簡単です。
メイソンウィーラー

3
@Mason本当の言葉。Javaのような言語は、関数が必然的にクラスに属するものであるという誤った概念を強制します。
KChaloux

5
これは良い答えですが、それでも完全な真実を伝えることはできません。静的メソッド非静的データにアクセスできます。暗黙的なオブジェクトやthis-referenceが利用できないだけです。理解することは非常に重要だと思います。
から来

2
@COMEFROM明示的に渡すということですか?私があなたを正しく理解していれば、私はそれをメモすることができます。すべての関数が明示的に渡されたデータを処理できることを考えると、静的メソッドが明示的に渡された非静的データにアクセスできることが暗示されていると想定しました。
KChaloux

22

仮説的なサンプルで説明しましょう。

簡単なクラスを想像してください:

class User
{
User(string n) { name = n; };
string name;
}

次に、このクラスの2つのインスタンスを作成します。

User Bones = new User("Bones");
User Jim = new User("Jim");

今、考えてみてください-ユーザーに新しい静的メソッドを追加した場合、例えば:

static string GetName();

そしてあなたはそれを呼ぶ:

string x = User::GetName()

xには何が含まれますか?「ジム」、「骨」、または他の何か?

問題は、静的メソッドがオブジェクトではなくクラスで定義された単一のメソッドであることです。その結果、どのオブジェクトに適用されるかわかりません。これが特別な理由です。静的メソッドは、たとえばCの関数のような個別の物と考えるのが最善です。Javaのような言語がクラス内に含まれていることは、主にJavaがクラス外に存在することを許可しないという問題であるため、このような関数は何らかの方法でクラス内に強制する必要があります(main()クラス内でも、すべての意味で、それが単一のスタンドアロン関数であるべきだと言っている場合)。


2

非静的データは、クラスのインスタンスに関連付けられています。静的メソッド(およびデータ)は、クラスの特定のインスタンスに関連付けられていません。静的メソッドを使用するクラスのインスタンスは必要ありません。インスタンスがあったとしても、Javaが静的メソッドを呼び出すときに期待するインスタンスで操作していることを保証する方法はありません。したがって、静的メソッドは非静的データにアクセスできません。


2

フィールドデータを使用できます。次のJavaコードを検討してください。

class MyBean {
    private String myString;

    static void myStaticMethod() {
        myString = "tada";/*not allowed; if this was possible how would 
                           be different from a field without static?*/

        MyBean myBean = new MyBean();//allowed if associated with an instance
        myBean.myString = "tada";
    }
}

これは技術的には非静的データを使用する静的メソッドかもしれませんが、ポイントを逃しています。もちろん、新しいインスタンスを作成してアクセスできます。しかし、それは本質とはまったく関係ありませんstatic
ボブソン

2
実際、これはポイントを説明する上で非常に良い追加だと思います。静的メソッドが非静的データにアクセスできるようになる前に、静的メソッドがクラスのインスタンスを必要とする点を強調し、その理由を直感的に説明します。
ベンホッキング

@Bobsonコードとコメントも読む必要があります。
m3th0dman

@BenHocking「はい」でも、私は「インスタンス変数は常にオブジェクトに関連付けられている」という良い点占いだと思う
JAVA

2

ここでの問題は理解の問題だと思います。

技術的な観点からは、オブジェクト内から呼び出される静的メソッドは、インスタンスフィールドを非常に見ることができます。そもそもこれが問題の原因であると強く思う。

問題は、オブジェクトの外部からメソッドを呼び出すことができることです。その時点では、それらを提供するインスタンスデータはありません。したがって、コンパイラがコードを解決する方法はありません。インスタンスデータを許可すると矛盾が発生するため、インスタンスデータを許可してはなりません。


同意しません。インスタンスデータにはオブジェクトのインスタンスを介してアクセスする必要があり、静的メソッドは特定のインスタンスに関連付けられていない(ただし、クラス定義に関連付けられている)ため、静的メソッドはインスタンスデータにアクセスできません。
フィルW.

あなたは私のポイントを逃します。 クラス内から呼び出された場合、コンパイラは、静的クラスではない場合のようにインスタンスポインタを渡すことができます。別の場所から呼ばれていた場合に問題が来る- (。内部で基本的に静的を無視してはいえ)プライベート静的メソッドはインスタンスデータにアクセスできることを意味する
ローレンPechtel

はい、コンパイラは/ could /ですが、なぜそうすべきですか?このようなポインターを渡すと、基本的にインスタンスメソッドになります。これを行うことができるのはプライベートメソッドだけであるというあなたの規定は無意味です-リフレクションテクノロジーは/ all /メソッドをアクセス可能にする-プライベートかどうか-これをさらに危険な命題にします。レドモンドの私たちの友達は別の方向に向かっています。クラス自体ではなくオブジェクトインスタンスに対して静的メソッドを呼び出そうとすると、それらの言語は警告を発します。
フィルW.

1

オブジェクト指向ではない次元に存在する静的メソッドと考えてください。

「オブジェクト指向の次元」では、クラスは複数のエゴ(インスタンス)を生成できます。各エゴは、その状態によって自身の良心を持っています。

フラットでオブジェクト指向でない次元では、クラスはオブジェクト指向次元に住んでいる彼らのエゴを忘れています。彼らの世界は、OOPがまだ発明されていないかのように、クラスが小さな手続き型プログラムであり、静的データが単なるグローバル変数であるかのように、フラットで手続き型です。


1

これを説明する最も簡単な方法は、いくつかのコードを見て、そのコードが生成することを期待する結果を検討することだと思います。

// Create three new cars.  Cars have a name attribute.  
Car car1 = new Car("Mazda3");
Car car2 = new Car("FordFocus");
Car car3 = new Car("HondaFit");

// Now we would like to print the names of some cars: 
// First off why don't we try this: 

Car.printCarName();

// Expected behaviour: 
// If we think about what we are trying to do here it doesn't
// really make sense.  What instance of car name should this 
// print?  Should it print Mazda3?  FordFoucs?
// What is the expected behaviour?  If we are going to have a
// static call on car call printCarName it should probably do
// something like print all car names or a random car name or
// throw an error.  


//Now lets try this instead: 

Car.printCarName(car1);

// Expected Behaviour: 
// Luckily the expected behaviour is very clear here.  This
// should print Mazda3.  This works as expected.  


// Finally lets try this: 

car1.printMyName();

// Expected Behaviour:
// Same as previous example, however this is the *right* way
// to do it.  

完全を期すために、ここに車のクラスがあります:

public class Car{

    public String name;

    public Car(String name){
        this.name = name;
    }

    public static printCarName(){
        print "Not sure what to do here...  Don't know which car you are talking about.";
    }

    public static printCarName(Car c){
        print c.name;
    }

    public /*NOT static*/ printMyName(){
        print this.name;
    }

}

これは質問にどう答えますか?
gnat

1
@gnatを明確にするためにコメント付きで更新。
sixtyfootersdude

1

他の答えはほとんどすべてを言っていますが、追加したい「詳細」があります。

静的メソッド(Javaのメソッドなど)には、this通常は名前で直接アクセスできるメンバーを持つ暗黙的なオブジェクトが関連付けられていません(を介してアクセス可能)。

それは、彼らが非静的データにアクセスできないという意味ではありません。

class MyClass {
  public static void foo(MyOtherClass object) {
    System.out.println(object.member);
  }
}
class MyOtherClass { public int member = 10; }

これは詳細に過ぎませんが、読んだときにあなたの質問がおかしいと感じました。「静的データのみを使用できます」は制限が多すぎます。

ところで、私はコードをテストしませんでした。私が言っていることを例示するために、ここに書いただけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.