ทำไมตัวแปรอินเทอร์เฟซคงที่และครั้งสุดท้ายตามค่าเริ่มต้นใน Java?
ทำไมตัวแปรอินเทอร์เฟซคงที่และครั้งสุดท้ายตามค่าเริ่มต้นใน Java?
คำตอบ:
จากคำถามที่พบบ่อยการออกแบบอินเตอร์เฟส Java โดย Philip Shaw:
ตัวแปรอินเตอร์เฟสคงที่เนื่องจากอินเตอร์เฟส Java ไม่สามารถสร้างอินสแตนซ์ได้ในสิทธิ์ของตนเอง ต้องกำหนดค่าของตัวแปรในบริบทแบบสแตติกซึ่งไม่มีอินสแตนซ์อยู่ ตัวดัดแปลงสุดท้ายทำให้แน่ใจว่าค่าที่กำหนดให้กับตัวแปรอินเตอร์เฟสนั้นเป็นค่าคงที่จริงที่ไม่สามารถกำหนดใหม่ได้ด้วยรหัสโปรแกรม
static
ตัวดัดแปลงนี้ปลอมโดยสมบูรณ์ ตัวแปรอินสแตนซ์สาธารณะของคลาสเป็นส่วนหนึ่งของอินเทอร์เฟซและไม่มีเหตุผลว่าทำไมพวกเขาจึงไม่ควรมีนามธรรมใน Java interface
เช่นเดียวกับวิธีการอินสแตนซ์ ไม่สำคัญว่า Java interface
ไม่สามารถสร้างอินสแตนซ์ได้โดยตรงคุณยังสามารถมีอินสแตนซ์ของคลาสที่ใช้งานได้interface
และมีเหตุผลที่ต้องการให้พวกเขามีตัวแปรอินสแตนซ์สาธารณะที่แน่นอน ส่วนที่เกี่ยวกับfinal
ที่ไม่ได้ให้คำอธิบายใด ๆ - มันเพียงอธิบายสิ่งที่final
หมายถึง
เนื่องจากอินเตอร์เฟซไม่มีวัตถุโดยตรงวิธีเดียวในการเข้าถึงพวกมันคือการใช้คลาส / อินเตอร์เฟสและด้วยเหตุนี้ถ้าตัวแปรอินเทอร์เฟซมีอยู่มันควรจะคงที่มิฉะนั้นมันจะไม่สามารถเข้าถึงได้จากโลกภายนอก ขณะนี้เนื่องจากเป็นแบบคงที่มันสามารถเก็บค่าเดียวเท่านั้นและคลาสใด ๆ ที่ใช้มันสามารถเปลี่ยนได้และด้วยเหตุนี้มันจึงเป็นระเบียบทั้งหมด
ดังนั้นหากมีตัวแปรอินเตอร์เฟซก็จะคงที่โดยปริยายสุดท้ายและสาธารณะอย่างเห็นได้ชัด !!!
interface
Java คลาสจะใช้อินเทอร์เฟซเพื่อประกาศตัวแปรอินสแตนซ์ (ตามที่ต้องการโดยอินเตอร์เฟส) มันคอนสตรัค (หรือวิธีอื่น ๆ ) ตั้งค่าตัวแปรอินสแตนซ์ เมื่ออินสแตนซ์ของคลาสนั้นอินสแตนซ์คุณจะสามารถเข้าถึงตัวแปรอินสแตนซ์ของมัน
สาธารณะ : สำหรับการเข้าถึงในทุกชั้นเรียนเช่นเดียวกับวิธีการที่มีอยู่ในอินเทอร์เฟซ
คงที่ : เนื่องจากอินเตอร์เฟสไม่สามารถมีวัตถุได้ interfaceName.variableName สามารถใช้เพื่ออ้างอิงหรือตัวแปรโดยตรงในคลาสที่นำไปใช้
ขั้นสุดท้าย : เพื่อทำให้พวกเขาคงที่ หาก 2 คลาสใช้อินเตอร์เฟสเดียวกันและคุณให้สิทธิ์ในการเปลี่ยนค่าทั้งสองค่าความขัดแย้งจะเกิดขึ้นในค่าปัจจุบันของ var ซึ่งเป็นสาเหตุที่อนุญาตให้เริ่มต้นได้เพียงครั้งเดียวเท่านั้น
นอกจากนี้ตัวดัดแปลงเหล่านี้ทั้งหมดจะมีนัยสำหรับอินเทอร์เฟซคุณไม่จำเป็นต้องระบุใด ๆ เลย
( นี่ไม่ใช่คำตอบเชิงปรัชญา แต่เป็นคำตอบเชิงปฏิบัติมากกว่า ) ข้อกำหนดสำหรับstatic
ตัวดัดแปลงนั้นชัดเจนซึ่งผู้อื่นได้ตอบแล้ว โดยทั่วไปตั้งแต่การเชื่อมต่อที่ไม่สามารถ instantiated วิธีเดียวที่จะเข้าถึงเขตข้อมูลที่มีเพื่อให้ข้อมูลชั้นเรียน static
-
เหตุผลที่อยู่เบื้องหลังinterface
เขตข้อมูลกลายเป็นโดยอัตโนมัติfinal
(คงที่) คือการป้องกันการใช้งานที่แตกต่างกันโดยไม่ตั้งใจเปลี่ยนค่าของตัวแปรอินเตอร์เฟสซึ่งอาจส่งผลกระทบต่อพฤติกรรมของการใช้งานอื่น ๆ โดยไม่ได้ตั้งใจ ลองนึกภาพสถานการณ์ด้านล่างที่interface
ทรัพย์สินไม่ได้เป็นfinal
Java อย่างชัดเจน:
public interface Actionable {
public static boolean isActionable = false;
public void performAction();
}
public NuclearAction implements Actionable {
public void performAction() {
// Code that depends on isActionable variable
if (isActionable) {
// Launch nuclear weapon!!!
}
}
}
ทีนี้ลองคิดดูสิว่าจะเกิดอะไรขึ้นถ้าคลาสอื่นที่ปรับActionable
เปลี่ยนสถานะของตัวแปรอินเตอร์เฟส:
public CleanAction implements Actionable {
public void performAction() {
// Code that can alter isActionable state since it is not constant
isActionable = true;
}
}
หากคลาสเหล่านี้ถูกโหลดภายใน JVM เดียวโดย classloader ดังนั้นพฤติกรรมของNuclearAction
สามารถได้รับผลกระทบจากคลาสอื่นCleanAction
เมื่อperformAction()
มีการเรียกใช้หลังจากCleanAction
ที่มีการดำเนินการ (ในเธรดเดียวกันหรืออย่างอื่น) ซึ่งในกรณีนี้อาจเป็นหายนะ (ความหมายนั่นคือ)
เนื่องจากเราไม่ทราบว่าการนำไปปฏิบัติแต่ละครั้งinterface
จะใช้ตัวแปรเหล่านี้final
อย่างไร
เนื่องจากสิ่งอื่นเป็นส่วนหนึ่งของการนำไปใช้และอินเตอร์เฟสไม่สามารถมีการนำไปใช้งานได้
public interface A{
int x=65;
}
public interface B{
int x=66;
}
public class D implements A,B {
public static void main(String[] a){
System.out.println(x); // which x?
}
}
นี่คือทางออก
System.out.println(A.x); // done
ฉันคิดว่ามันเป็นเหตุผลหนึ่งที่ตัวแปรอินเตอร์เฟซคงที่
อย่าประกาศตัวแปรภายในส่วนต่อประสาน
static final
ก่อนหน้าตัวแปรที่เป็นแบบสแตติกและสุดท้าย
คงที่ - เพราะอินเตอร์เฟซไม่สามารถมีตัวอย่างใด ๆ และสุดท้าย - เพราะเราไม่จำเป็นต้องเปลี่ยน
เพราะ:
Static
: เนื่องจากเราไม่สามารถมีวัตถุของอินเตอร์เฟสได้ดังนั้นเราจึงควรหลีกเลี่ยงการใช้ตัวแปรระดับสมาชิก Object และควรใช้ตัวแปรระดับ class เช่น static
Final
: เพื่อให้เราไม่ควรมีค่าที่ไม่ชัดเจนสำหรับตัวแปร (ปัญหาเพชร - การสืบทอดหลายอย่าง)
และเป็นไปตามเอกสารประกอบการติดต่อเป็นสัญญาและไม่ดำเนินการ
การอ้างอิง: คำตอบของ Abhishek Jain เกี่ยวกับโควต้า
Java ไม่อนุญาตให้ใช้ตัวแปรเชิงนามธรรมและ / หรือคำจำกัดความของตัวสร้างในอินเตอร์เฟส การแก้ไข: เพียงแค่วางคลาสนามธรรมระหว่างอินเทอร์เฟซของคุณและการใช้งานของคุณซึ่งจะขยายคลาสนามธรรมเช่นนั้น:
public interface IMyClass {
void methodA();
String methodB();
Integer methodC();
}
public abstract class myAbstractClass implements IMyClass {
protected String varA, varB;
//Constructor
myAbstractClass(String varA, String varB) {
this.varA = varA;
this.varB = VarB;
}
//Implement (some) interface methods here or leave them for the concrete class
protected void methodA() {
//Do something
}
//Add additional methods here which must be implemented in the concrete class
protected abstract Long methodD();
//Write some completely new methods which can be used by all subclasses
protected Float methodE() {
return 42.0;
}
}
public class myConcreteClass extends myAbstractClass {
//Constructor must now be implemented!
myClass(String varA, String varB) {
super(varA, varB);
}
//All non-private variables from the abstract class are available here
//All methods not implemented in the abstract class must be implemented here
}
นอกจากนี้คุณยังสามารถใช้คลาสนามธรรมโดยไม่ต้องมีอินเทอร์เฟซใด ๆ หากคุณแน่ใจว่าคุณไม่ต้องการใช้พร้อมกับอินเตอร์เฟสอื่น ๆ โปรดทราบว่าคุณไม่สามารถสร้างตัวอย่างของคลาสนามธรรมที่คุณต้องขยายก่อน
(คำหลัก "ป้องกัน" หมายความว่าเฉพาะคลาสที่ขยายเท่านั้นที่สามารถเข้าถึงวิธีการและตัวแปรเหล่านี้ได้)
สไปโร
อินเตอร์เฟส: บริการตามความต้องการของระบบ
ในอินเทอร์เฟซตัวแปรจะเป็นค่าเริ่มต้นที่กำหนดโดยตัวดัดแปลงการเข้าถึงสาธารณะแบบคงที่และสุดท้าย เพราะ :
สาธารณะ:มันเกิดขึ้นบางครั้งอินเทอร์เฟซที่อาจวางไว้ในแพคเกจอื่น ๆ ดังนั้นจึงจำเป็นต้องเข้าถึงตัวแปรจากที่ใดก็ได้ในโครงการ
คงที่:เป็นชั้นเรียนที่ไม่สมบูรณ์ดังกล่าวไม่สามารถสร้างวัตถุ ดังนั้นในโครงการเราจำเป็นต้องเข้าถึงตัวแปรโดยไม่มีวัตถุเพื่อให้เราสามารถเข้าถึงด้วยความช่วยเหลือของinterface_filename.variable_name
final:สมมติว่าหนึ่งอินเตอร์เฟสใช้หลายคลาสและคลาสทั้งหมดพยายามเข้าถึงและอัพเดตตัวแปรอินเตอร์เฟส ดังนั้นจึงนำไปสู่การเปลี่ยนแปลงข้อมูลที่ไม่สอดคล้องและส่งผลกระทบต่อคลาสอื่น ๆ ทุกคลาส ดังนั้นจึงจำเป็นต้องประกาศตัวปรับปรุงการเข้าถึงด้วยขั้นตอนสุดท้าย
ในJava
อินเทอร์เฟซไม่อนุญาตให้คุณประกาศตัวแปรอินสแตนซ์ใด ๆ การใช้ตัวแปรที่ประกาศในอินเตอร์เฟสเป็นตัวแปรอินสแตนซ์จะส่งคืนข้อผิดพลาดในเวลาคอมไพล์
คุณสามารถประกาศตัวแปรคงที่โดยใช้static final
ซึ่งแตกต่างจากตัวแปรอินสแตนซ์
อินเทอร์เฟซสามารถใช้งานได้โดยคลาสใด ๆ และจะเกิดอะไรขึ้นถ้าค่านั้นเปลี่ยนไปโดยการใช้คลาสใดคลาสหนึ่งจะทำให้เข้าใจผิดสำหรับคลาสที่ใช้งานอื่น ๆ อินเทอร์เฟซนั้นเป็นการอ้างอิงเพื่อรวมสอง corelated แต่เอนทิตีที่แตกต่างกันดังนั้นเหตุผลที่ประกาศตัวแปรภายในอินเทอร์เฟซจะเป็นขั้นสุดท้าย
ลองนึกถึงเว็บแอปพลิเคชั่นที่คุณกำหนดอินเทอร์เฟซไว้และคลาสอื่น ๆ จะใช้มัน เนื่องจากคุณไม่สามารถสร้างอินสแตนซ์ของอินเทอร์เฟซเพื่อเข้าถึงตัวแปรที่คุณต้องมีคำหลักคงที่ เนื่องจากค่าคงที่การเปลี่ยนแปลงใด ๆ ในค่าจะสะท้อนถึงอินสแตนซ์อื่น ๆ ที่มีการใช้งาน ดังนั้นเพื่อป้องกันไม่ให้เรากำหนดพวกเขาเป็นที่สิ้นสุด
เพิ่งลองใช้ Eclipse ตัวแปรในอินเทอร์เฟซจะเป็นค่าเริ่มต้นดังนั้นคุณจึงไม่สามารถเปลี่ยนแปลงได้ เมื่อเทียบกับระดับผู้ปกครองตัวแปรสามารถเปลี่ยนแปลงได้อย่างแน่นอน ทำไม? จากจุดของฉันตัวแปรในชั้นเรียนเป็นคุณลักษณะที่จะได้รับการสืบทอดโดยเด็กและเด็ก ๆ สามารถเปลี่ยนได้ตามความต้องการที่แท้จริงของพวกเขา ในทางตรงกันข้ามอินเตอร์เฟสจะกำหนดพฤติกรรมเท่านั้นไม่ใช่แอตทริบิวต์ เหตุผลเดียวในการใส่ตัวแปรในอินเตอร์เฟสคือใช้เป็น const ซึ่งเกี่ยวข้องกับอินเตอร์เฟสนั้น แม้ว่านี่ไม่ใช่วิธีปฏิบัติที่ดีตามข้อความที่ตัดตอนมาดังต่อไปนี้:
"การวางค่าคงที่ในส่วนต่อประสานเป็นเทคนิคที่ได้รับความนิยมในยุคแรก ๆ ของ Java แต่ตอนนี้หลายคนคิดว่ามันเป็นการใช้อินเตอร์เฟสที่น่ารังเกียจเนื่องจากส่วนต่อประสานควรจัดการกับบริการที่จัดทำโดยวัตถุไม่ใช่ข้อมูลเช่นเดียวกับค่าคงที่ที่ใช้ โดยปกติแล้วคลาสจะมีรายละเอียดการใช้งาน แต่การวางไว้ในส่วนต่อประสานจะส่งเสริมให้พวกเขาเป็น API สาธารณะของชั้นเรียน "
ฉันพยายามใส่แบบคงที่หรือไม่สร้างความแตกต่างเลย รหัสดังต่อไปนี้:
public interface Addable {
static int count = 6;
public int add(int i);
}
public class Impl implements Addable {
@Override
public int add(int i) {
return i+count;
}
}
public class Test {
public static void main(String... args) {
Impl impl = new Impl();
System.out.println(impl.add(4));
}
}