ทำไมวิธีการแบบคงที่สามารถใช้ข้อมูลแบบคงที่เท่านั้น?


38

ฉันไม่เข้าใจว่าทำไมวิธีการคงที่ไม่สามารถใช้ข้อมูลที่ไม่คงที่ได้ ใครช่วยอธิบายได้ว่าปัญหาคืออะไรและทำไมเราถึงทำไม่ได้?


11
เพราะข้อมูลคงที่เท่านั้นจากมุมมองของวิธีการคงที่
mouviciel

4
การแชร์งานวิจัยของคุณช่วยให้ทุกคน บอกเราว่าคุณได้ลองทำอะไรและทำไมมันถึงไม่ตรงกับความต้องการของคุณ สิ่งนี้แสดงให้เห็นว่าคุณได้ใช้เวลาในการพยายามช่วยตัวเองมันช่วยให้เราไม่ต้องย้ำคำตอบที่ชัดเจนและส่วนใหญ่จะช่วยให้คุณได้คำตอบที่เฉพาะเจาะจงและเกี่ยวข้องมากขึ้น ดูวิธีถาม
gnat

19
@gnat ในกรณีนี้ OP พยายามเข้าใจเหตุผลที่อยู่เบื้องหลังการตัดสินใจออกแบบ คุณคาดหวังให้เขาลองทำอะไรในกรณีนี้?
Geek

2
@Geek - การมีอยู่ของวิธีการคงที่ข้อมูลคงที่เป็นปัญหาการออกแบบภาษา สมมติว่าความหมายมาตรฐานความจริงที่ว่าวิธีการคงที่ไม่สามารถเข้าถึงข้อมูลอินสแตนซ์ไม่ได้ ข้อ จำกัด ดังกล่าวมีความหมายโดยนัยและสิ่งที่เป็นไปได้และสมเหตุสมผล
Steve314

6
ในการถอดความเกอร์ทรูดสไตน์: "ไม่มีสิ่งนี้อยู่ที่นั่น"
hippo-dancer

คำตอบ:


73

ในส่วนภาษา OO เมื่อคุณกำหนดวิธีการที่อยู่ภายในชั้นเรียนมันจะกลายเป็นวิธีที่อินสแตนซ์ เมื่อคุณสร้างอินสแตนซ์ใหม่ของคลาสนั้นโดยใช้newคีย์เวิร์ดคุณจะกำหนดค่าเริ่มต้นชุดข้อมูลใหม่ให้เป็นอินสแตนซ์นั้นได้ เมธอดที่เป็นของอินสแตนซ์นั้นสามารถทำงานกับข้อมูลที่คุณกำหนดไว้ได้

วิธีการคงที่ในทางตรงกันข้ามจะไม่รู้ของอินสแตนซ์ของแต่ละชั้นเรียน วิธีการคงที่จะคล้ายกับฟังก์ชั่นฟรีใน C หรือ C ++ มันไม่ได้เชื่อมโยงกับการสร้างอินสแตนซ์ที่เฉพาะเจาะจงของชั้นเรียน นี่คือเหตุผลที่พวกเขาไม่สามารถเข้าถึงค่าอินสแตนซ์ ไม่มีอินสแตนซ์ที่จะรับค่าจาก!

ข้อมูลคงที่คล้ายกับวิธีการคงที่ ค่าที่ถูกประกาศstaticไม่มีอินสแตนซ์ที่เกี่ยวข้อง มันมีอยู่สำหรับทุกอินสแตนซ์และมีการประกาศในที่เดียวในหน่วยความจำเท่านั้น หากมีการเปลี่ยนแปลงมันจะเปลี่ยนไปสำหรับทุก ๆ ครั้งของคลาสนั้น

วิธีคงสามารถเข้าถึงข้อมูลแบบคงที่เพราะพวกเขาทั้งสองอยู่เป็นอิสระจากกรณีที่เฉพาะเจาะจงของชั้นเรียน

มันอาจช่วยให้ดูว่าคุณใช้วิธีการคงที่อย่างไรเมื่อเปรียบเทียบกับวิธีการอินสแตนซ์ สมมติว่าเรามีคลาสต่อไปนี้ (ใช้ pseudocode เหมือน 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
สิ่งนี้มีความซับซ้อนน้อยกว่ามากในการอธิบายในภาษาที่ไม่บังคับให้ทุกอย่างเป็นส่วนหนึ่งของวัตถุโดยค่าเริ่มต้น
Mason Wheeler

3
@Mason คำที่แท้จริง ภาษาอย่าง Java บังคับความคิดผิด ๆ ว่าฟังก์ชั่นเป็นสิ่งที่จำเป็นต้องเป็นของคลาส
KChaloux

5
นี่เป็นคำตอบที่ดี แต่ก็ยังล้มเหลวในการบอกความจริงทั้งหมด: วิธีการคงที่สามารถเข้าถึงข้อมูลที่ไม่คงที่ พวกเขาไม่มีวัตถุโดยนัยหรือ - การthisอ้างอิงที่พร้อมใช้งาน ฉันคิดว่ามันเป็นสิ่งสำคัญอย่างยิ่งที่จะเข้าใจ
จาก

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 จะบรรจุอะไร? "Jim", "Bones" หรืออะไรอย่างอื่น?

ปัญหาคือว่าวิธีการคงที่เป็นวิธีการเดียวที่กำหนดไว้ในชั้นเรียนไม่ใช่วัตถุ ดังนั้นคุณจึงไม่ทราบว่าอาจใช้วัตถุใด นี่คือเหตุผลที่มันเป็นสิ่งที่พิเศษ เป็นการดีที่สุดที่จะคิดว่าวิธีการคงที่เป็นสิ่งที่แต่ละบุคคลเช่นฟังก์ชั่นใน C เช่น ภาษาอย่าง Java ที่มีอยู่ในคลาสนั้นส่วนใหญ่เป็นปัญหาของ Java ที่ไม่อนุญาตให้มีสิ่งใดอยู่นอกคลาสดังนั้นฟังก์ชันเช่นนี้จะต้องถูกบังคับภายในคลาสในลักษณะบางอย่าง ภายในชั้นเรียนด้วยเมื่อทุกคนรู้สึกว่ามันควรจะเป็นฟังก์ชั่นเอกพจน์และเป็นเอกเทศ)


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

ขณะนี้ในทางเทคนิคอาจเป็นวิธีการคงที่โดยใช้ข้อมูลที่ไม่คงที่ก็หายไปจุด แน่นอนคุณสามารถสร้างอินสแตนซ์ใหม่และเข้าถึงได้ แต่นั่นไม่เกี่ยวอะไรกับstaticness
Bobson

2
อันที่จริงฉันคิดว่านี่เป็นส่วนเสริมที่ดีมากในการอธิบายประเด็น มันเน้นจุดที่วิธีการแบบคงที่ต้องการอินสแตนซ์ของคลาสก่อนที่จะสามารถเข้าถึงข้อมูลไม่คงที่ในขณะที่ให้เหตุผลง่าย ๆ ที่เป็นเช่นนั้น
Ben Hocking

@ Bobon คุณควรอ่านรหัสและความคิดเห็นด้วย
m3th0dman

@BenHocking "ใช่" แม้ฉันคิดว่ามันเป็นจุดที่ดีบอกว่า "ตัวแปรเช่นมีความเกี่ยวข้องเสมอกับวัตถุ"
JAVA

2

ฉันคิดว่าปัญหาที่นี่เป็นหนึ่งในความเข้าใจ

จากมุมมองทางเทคนิควิธีการแบบคงที่ที่เรียกจากภายในวัตถุจะค่อนข้างสามารถดูเขตข้อมูลอินสแตนซ์ ฉันสงสัยอย่างยิ่งว่านี่คือสิ่งที่ทำให้เกิดคำถามตั้งแต่แรก

ปัญหาคือวิธีการที่สามารถเรียกได้จากนอกวัตถุ ณ จุดนี้ไม่มีข้อมูลอินสแตนซ์ที่จะให้พวกเขา - ดังนั้นจึงไม่มีวิธีสำหรับคอมไพเลอร์ในการแก้ไขรหัส เนื่องจากการอนุญาตข้อมูลอินสแตนซ์ทำให้เกิดความขัดแย้งเราจะต้องไม่อนุญาตข้อมูลอินสแตนซ์


ฉันไม่เห็นด้วย. วิธีสแตติกไม่สามารถเข้าถึงข้อมูลอินสแตนซ์ได้เนื่องจากข้อมูลอินสแตนซ์จะต้องเข้าถึงได้ผ่านอินสแตนซ์ของวัตถุและวิธีสแตติกไม่เชื่อมโยงกับอินสแตนซ์ที่กำหนดใด ๆ (แต่มีการกำหนดคลาส)
Phill W.

คุณคิดถึงจุดของฉัน ถ้ามันถูกเรียกจากภายในคลาสคอมไพเลอร์สามารถส่งผ่านตัวชี้อินสแตนซ์เหมือนที่มันทำเมื่อไม่ใช่คลาสแบบสแตติก ปัญหาเกิดขึ้นถ้ามันถูกเรียกจากที่อื่น - ซึ่งหมายความว่าวิธีการคงที่ส่วนตัวสามารถเข้าถึงข้อมูลอินสแตนซ์ (แม้ว่าโดยทั่วไปจะไม่สนใจสแตติกภายใน)
Loren Pechtel

ใช่คอมไพเลอร์ / ได้ / แต่ทำไมมันควร? ผ่านตัวชี้ดังกล่าวเป็นหลักช่วยลดมันเป็นวิธีการตัวอย่าง ข้อตกลงของคุณว่าเป็นเพียงวิธีส่วนตัวที่สามารถทำสิ่งนี้ได้คือ moot - เทคโนโลยีการสะท้อนทำให้ / ทั้งหมด / วิธีการเข้าถึง - เป็นส่วนตัวหรือไม่ - ทำให้สิ่งนี้เป็นข้อเสนอที่มีความเสี่ยงมากยิ่งขึ้น เพื่อนของเราในเรดมันด์ได้ไปในอีกทางหนึ่ง ภาษาของพวกเขาจะส่งสัญญาณเตือนหากคุณพยายามเรียกใช้เมธอดแบบสแตติกกับอินสแตนซ์ของวัตถุ (และไม่ใช่คลาสเอง)
Phill W.

1

คิดว่ามันเป็นวิธีการคงที่อาศัยอยู่ในมิติที่ไม่ใช่เชิงวัตถุ

ใน "มิติเชิงวัตถุ" คลาสสามารถวางไข่ทวีคูณ egos (อินสแตนซ์) แต่ละอัตตามีมโนธรรมของตัวเองผ่านสถานะของมัน

ในแบนไม่ใช่มิติ OO ชั้นจะลืมอัตตาของพวกเขาอาศัยอยู่ในมิติ OO โลกของพวกเขานั้นเรียบและเป็นขั้นตอนราวกับว่า 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;
    }

}

คำถามนี้ถามคำถามนี้อย่างไร
ริ้น

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.