Mengapa metode statis hanya menggunakan data statis?


38

Saya tidak mengerti mengapa metode statis tidak dapat menggunakan data non-statis. Adakah yang bisa menjelaskan apa masalahnya dan mengapa kita tidak bisa melakukannya?


11
Karena hanya data statis yang ada dari sudut pandang metode statis.
mouviciel

4
Berbagi penelitian Anda membantu semua orang. Beri tahu kami apa yang telah Anda coba dan mengapa itu tidak memenuhi kebutuhan Anda. Ini menunjukkan bahwa Anda telah meluangkan waktu untuk mencoba membantu diri sendiri, itu menyelamatkan kami dari mengulangi jawaban yang jelas, dan yang paling utama itu membantu Anda mendapatkan jawaban yang lebih spesifik dan relevan. Lihat juga Cara Meminta
nyamuk

19
@gnat dalam hal ini OP sedang mencoba memahami alasan di balik keputusan desain. Apa yang Anda harapkan dari dia dalam kasus ini?
Geek

2
@ Geek - adanya metode statis, data statis adalah masalah desain bahasa. Dengan asumsi makna standar, fakta bahwa metode statis tidak dapat mengakses data contoh tidak. Keterbatasan tersirat oleh definisi dan apa yang mungkin dan masuk akal, bukan oleh beberapa perancang bahasa kelemahan.
Steve314

6
Mengutip Gertrude Stein: "Tidak ada ini di sana."
penari kuda nil

Jawaban:


73

Di sebagian besar bahasa OO, ketika Anda mendefinisikan metode di dalam kelas, itu menjadi Metode Instance . Saat Anda membuat instance baru dari kelas itu, melalui newkata kunci, Anda menginisialisasi kumpulan data baru yang unik hanya untuk instance itu. Metode milik instance itu kemudian dapat bekerja dengan data yang Anda tetapkan di atasnya.

Metode statis , sebaliknya, tidak mengetahui contoh kelas individu. Metode statis mirip dengan fungsi bebas di C atau C ++. Itu tidak terikat pada Instansiasi khusus kelas. Inilah sebabnya mereka tidak dapat mengakses nilai instance. Tidak ada contoh untuk mengambil nilai dari!

Data Statis mirip dengan metode statis. Nilai yang dideklarasikan statictidak memiliki turunan terkait. Itu ada untuk setiap contoh, dan hanya dinyatakan dalam satu tempat di memori. Jika itu pernah diubah, itu akan berubah untuk setiap instance dari kelas itu.

Sebuah Metode statis dapat mengakses data statis karena mereka berdua ada secara independen dari contoh-contoh spesifik dari kelas.

Mungkin membantu untuk melihat bagaimana Anda menjalankan metode statis, dibandingkan dengan metode contoh. Katakanlah kita memiliki kelas berikut (menggunakan pseudocode Java-like):

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)

Memperbarui

Sebagai DATANG DARI poin di komentar, metode statis adalah mampu bekerja dengan data non-statis, tetapi harus dilalui secara eksplisit. Mari kita asumsikan Fookelas memiliki metode lain:

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

Addmasih statis, dan tidak memiliki valueturunannya sendiri, tetapi sebagai anggota kelas Foo, ia dapat mengakses valuebidang privat dari pass-in foo1dan foo2turunan. Dalam hal ini, kami menggunakannya untuk mengembalikan yang baru Foo dengan nilai tambah dari kedua nilai yang diteruskan.

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

30
Memperluas pada "Tidak ada contoh untuk mengambil nilai dari" - bahkan jika ada kasus, metode statis tidak dapat mengetahui mana misalnya untuk mengambil nilai dari.
Steve314

9
Ini jauh lebih rumit untuk dijelaskan dalam bahasa yang tidak memaksa semuanya menjadi bagian dari objek secara default.
Mason Wheeler

3
@Mason Kata-kata yang benar. Bahasa-bahasa seperti Java semacam menegakkan anggapan keliru bahwa suatu fungsi adalah sesuatu yang harus dimiliki kelas.
KChaloux

5
Ini adalah jawaban yang baik tetapi masih gagal untuk mengatakan kebenaran keseluruhan: metode statis dapat mengakses data non-statis. Mereka tidak memiliki objek implisit atau this-referensi yang tersedia. Saya pikir itu sangat penting untuk dipahami.
DATANG DARI

2
@COMEFROM Maksud Anda dengan passing eksplisit? Saya bisa mencatatnya, jika saya mengerti Anda dengan benar. Saya berasumsi itu tersirat bahwa metode statis dapat mengakses secara eksplisit melewati data non-statis, mengingat bahwa setiap fungsi dapat bekerja pada data yang secara eksplisit diteruskan ke sana.
KChaloux

22

Mari kita jelaskan dengan sampel hipotetis.

Bayangkan sebuah kelas sederhana:

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

Sekarang kita membuat 2 instance dari kelas ini:

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

sekarang, pikirkan - bagaimana jika kita menambahkan metode statis baru ke Pengguna, misalnya:

static string GetName();

dan Anda menyebutnya:

string x = User::GetName()

apa yang akan berisi x? "Jim", "Bones", atau yang lainnya?

Masalahnya adalah bahwa metode statis adalah metode tunggal, yang didefinisikan pada kelas, bukan objek. Akibatnya, Anda tidak tahu ke objek mana itu mungkin berlaku. Inilah sebabnya mengapa ini hal yang istimewa. Yang terbaik untuk memikirkan metode statis sebagai hal-hal individual, seperti fungsi dalam C misalnya. Bahwa bahasa-bahasa seperti Java mengandungnya di dalam kelas-kelas terutama merupakan masalah dengan Java yang tidak mengizinkan apa pun ada di luar kelas, jadi fungsi-fungsi seperti ini harus dipaksa di dalam suatu kelas dengan cara tertentu (agak seperti bagaimana main () dipaksa menjadi di dalam kelas juga ketika semua akal mengatakan itu harus fungsi tunggal, mandiri).


3

Itu bisa menggunakan data lapangan; pertimbangkan kode java berikut:

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";
    }
}

Meskipun ini secara teknis bisa menjadi metode statis menggunakan data non-statis, itu melenceng. Tentu saja Anda dapat membuat instance baru dan mengaksesnya. Tapi itu tidak ada hubungannya sama sekali dengan staticness.
Bobson

2
Sebenarnya, saya pikir ini adalah tambahan yang sangat bagus untuk menjelaskan intinya. Ini menyoroti titik bahwa metode statis membutuhkan turunan kelas sebelum dapat mengakses data non-statis sambil memberikan alasan intuitif mengapa demikian.
Ben Hocking

@ Bobson Anda harus membaca kode dan komentar juga.
m3th0dman

@BenHocking "ya" bahkan saya pikir itu adalah titik yang baik mengatakan bahwa "variabel instan selalu dikaitkan dengan objek"
JAVA

2

Data non-statis dikaitkan dengan turunan kelas. Metode statis (dan data) tidak terkait dengan instance kelas tertentu. Tidak perlu menjadi instance dari kelas untuk menggunakan metode statis di atasnya. Bahkan jika ada instance (s), tidak akan ada cara bagi Java untuk menjamin bahwa Anda beroperasi pada instance yang Anda harapkan ketika Anda memanggil metode statis. Oleh karena itu, metode statis tidak dapat memiliki akses ke data non-statis.


2

Saya pikir masalahnya adalah pemahaman.

Dari sudut pandang teknis, metode statis yang dipanggil dari dalam suatu objek akan cukup mampu melihat bidang instance. Saya sangat curiga inilah yang menyebabkan pertanyaan itu.

Masalahnya adalah bahwa metode dapat dipanggil dari luar objek. Pada saat itu tidak ada data instance untuk menyediakannya - dan dengan demikian tidak ada cara bagi kompiler untuk menyelesaikan kode. Karena mengizinkan data instan menyebabkan kontradiksi, kita tidak boleh mengizinkan data instan.


Saya tidak setuju. Metode statis tidak dapat mengakses data instance karena data instance harus diakses melalui instance objek dan metode statis tidak terkait dengan instance yang diberikan (tetapi dengan definisi kelas).
Phill W.

Anda melewatkan poin saya. Jika dipanggil dari dalam kelas, kompiler dapat melewatkan sebuah instance pointer seperti ketika tidak kelas statis. Masalahnya muncul jika dipanggil dari tempat lain - yang berarti metode statis privat dapat mengakses data contoh (meskipun secara internal mengabaikan statis.)
Loren Pechtel

Ya, kompiler / bisa / tetapi mengapa harus begitu? Melewati pointer semacam itu pada dasarnya menguranginya menjadi metode instance. Ketentuan Anda bahwa hanya metode pribadi yang dapat melakukan ini diperdebatkan - Teknologi refleksi membuat / semua / metode dapat diakses - pribadi atau tidak - menjadikan ini proposisi yang lebih berisiko. Teman-teman kita di Redmond pergi ke arah lain; bahasa mereka memunculkan peringatan jika Anda mencoba memanggil metode statis terhadap instance objek (dan bukan kelas itu sendiri).
Phill W.

1

Anggap saja sebagai metode statis yang hidup dalam dimensi yang tidak berorientasi objek.

Dalam "dimensi berorientasi objek" suatu kelas dapat menelurkan banyak ego (contoh), setiap ego memiliki hati nurani sendiri melalui kondisinya.

Dalam flat, dimensi non-OO suatu kelas tidak menyadari ego mereka yang hidup dalam dimensi OO. Dunia mereka datar dan prosedural, hampir seolah-olah OOP belum ditemukan, dan seolah-olah kelas adalah program prosedural kecil, dan data statis hanyalah variabel global.


1

Saya pikir cara termudah untuk menjelaskan ini adalah dengan melihat beberapa kode dan kemudian mempertimbangkan hasil apa yang kita harapkan dihasilkan oleh kode.

// 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.  

Untuk kelengkapan di sini adalah kelas mobil:

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;
    }

}

bagaimana ini menjawab pertanyaan yang diajukan?
nyamuk

1
@gnat Diperbarui dengan komentar untuk diklarifikasi.
sixtyfootersdude

1

Jawaban lain cukup banyak mengatakan itu semua, namun, ada beberapa "detail" yang ingin saya tambahkan.

Metode statis (misalnya yang ada di Jawa) tidak memiliki objek implisit yang terkait dengannya (dapat diakses melalui this) yang anggotanya dapat Anda akses biasanya langsung dengan namanya.

Itu tidak berarti mereka tidak dapat mengakses data non-statis.

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

Saya tahu ini hanya detail, tetapi saya menemukan pertanyaan Anda aneh ketika saya membacanya. "Hanya dapat menggunakan data statis" terlalu ketat.

Ngomong-ngomong, saya tidak menguji kode, saya hanya menulisnya di sini untuk memberikan contoh apa yang saya katakan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.