ฉันไม่เข้าใจว่าทำไมวิธีการคงที่ไม่สามารถใช้ข้อมูลที่ไม่คงที่ได้ ใครช่วยอธิบายได้ว่าปัญหาคืออะไรและทำไมเราถึงทำไม่ได้?
ฉันไม่เข้าใจว่าทำไมวิธีการคงที่ไม่สามารถใช้ข้อมูลที่ไม่คงที่ได้ ใครช่วยอธิบายได้ว่าปัญหาคืออะไรและทำไมเราถึงทำไม่ได้?
คำตอบ:
ในส่วนภาษา 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
this
อ้างอิงที่พร้อมใช้งาน ฉันคิดว่ามันเป็นสิ่งสำคัญอย่างยิ่งที่จะเข้าใจ
ให้อธิบายด้วยตัวอย่างสมมุติ
ลองนึกภาพคลาสที่เรียบง่าย:
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 ที่ไม่อนุญาตให้มีสิ่งใดอยู่นอกคลาสดังนั้นฟังก์ชันเช่นนี้จะต้องถูกบังคับภายในคลาสในลักษณะบางอย่าง ภายในชั้นเรียนด้วยเมื่อทุกคนรู้สึกว่ามันควรจะเป็นฟังก์ชั่นเอกพจน์และเป็นเอกเทศ)
ข้อมูลที่ไม่คงที่เชื่อมโยงกับอินสแตนซ์ของคลาส วิธีการแบบสแตติก (และข้อมูล) ไม่เกี่ยวข้องกับอินสแตนซ์เฉพาะของคลาส ไม่จำเป็นต้องมีอินสแตนซ์ของคลาสเพื่อใช้วิธีการคงที่กับมัน แม้ว่าจะมีอินสแตนซ์ แต่ก็ไม่มีทางที่ Java จะรับประกันได้ว่าคุณกำลังทำงานบนอินสแตนซ์ที่คุณคาดหวังเมื่อคุณเรียกใช้เมธอดแบบคงที่ ดังนั้นวิธีการคงที่ไม่สามารถเข้าถึงข้อมูลที่ไม่คงที่
มันสามารถใช้ข้อมูลภาคสนาม; พิจารณารหัส 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
ness
ฉันคิดว่าปัญหาที่นี่เป็นหนึ่งในความเข้าใจ
จากมุมมองทางเทคนิควิธีการแบบคงที่ที่เรียกจากภายในวัตถุจะค่อนข้างสามารถดูเขตข้อมูลอินสแตนซ์ ฉันสงสัยอย่างยิ่งว่านี่คือสิ่งที่ทำให้เกิดคำถามตั้งแต่แรก
ปัญหาคือวิธีการที่สามารถเรียกได้จากนอกวัตถุ ณ จุดนี้ไม่มีข้อมูลอินสแตนซ์ที่จะให้พวกเขา - ดังนั้นจึงไม่มีวิธีสำหรับคอมไพเลอร์ในการแก้ไขรหัส เนื่องจากการอนุญาตข้อมูลอินสแตนซ์ทำให้เกิดความขัดแย้งเราจะต้องไม่อนุญาตข้อมูลอินสแตนซ์
คิดว่ามันเป็นวิธีการคงที่อาศัยอยู่ในมิติที่ไม่ใช่เชิงวัตถุ
ใน "มิติเชิงวัตถุ" คลาสสามารถวางไข่ทวีคูณ egos (อินสแตนซ์) แต่ละอัตตามีมโนธรรมของตัวเองผ่านสถานะของมัน
ในแบนไม่ใช่มิติ OO ชั้นจะลืมอัตตาของพวกเขาอาศัยอยู่ในมิติ OO โลกของพวกเขานั้นเรียบและเป็นขั้นตอนราวกับว่า OOP นั้นยังไม่ได้ถูกประดิษฐ์ขึ้นมาและราวกับว่าคลาสนั้นเป็นโปรแกรมที่มีขั้นตอนเล็ก ๆ และข้อมูลคงที่เป็นเพียงตัวแปรทั่วโลก
ฉันคิดว่าวิธีที่ง่ายที่สุดในการอธิบายเรื่องนี้คือดูที่โค้ดแล้วพิจารณาผลลัพธ์ที่เราคาดหวังว่าโค้ดจะสร้างขึ้นมา
// 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;
}
}
คำตอบอื่น ๆ บอกได้เลยว่าทั้งหมดมี "รายละเอียด" บางอย่างที่ฉันต้องการเพิ่ม
วิธีการแบบคงที่ (พูดว่าใน Java) เพียงแค่ไม่มีวัตถุโดยนัยที่เกี่ยวข้องกับพวกเขา (เข้าถึงได้ผ่านthis
) ซึ่งสมาชิกที่คุณสามารถเข้าถึงได้โดยตรงมักจะชื่อ
ไม่ได้หมายความว่าพวกเขาไม่สามารถเข้าถึงข้อมูลที่ไม่คงที่ได้
class MyClass {
public static void foo(MyOtherClass object) {
System.out.println(object.member);
}
}
class MyOtherClass {
public int member = 10;
}
ฉันรู้ว่านี่เป็นเพียงรายละเอียด แต่ฉันพบว่าคำถามของคุณแปลกเมื่อฉันอ่าน "สามารถใช้ข้อมูลแบบคงที่เท่านั้น" มีข้อ จำกัด มากเกินไป
โดยวิธีการที่ฉันไม่ได้ทดสอบรหัสฉันเพิ่งเขียนมันที่นี่เพื่อเป็นตัวอย่างในสิ่งที่ฉันพูด