คำถามอยู่ใน Java ทำไมฉันไม่สามารถกำหนดวิธีคงที่นามธรรม? ตัวอย่างเช่น
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
คำถามอยู่ใน Java ทำไมฉันไม่สามารถกำหนดวิธีคงที่นามธรรม? ตัวอย่างเช่น
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
คำตอบ:
เพราะ "นามธรรม" หมายถึง: "ไม่มีฟังก์ชั่นการใช้งาน" และ "คงที่" หมายถึง: "มีฟังก์ชั่นแม้ว่าคุณจะไม่มีอินสแตนซ์ของวัตถุ" และนั่นคือความขัดแย้งเชิงตรรกะ
abstract static
จะทำให้รู้สึกที่สมบูรณ์แบบ มันจะเป็นวิธีการของวัตถุคลาสตัวเองซึ่งวัตถุ subclass ต้องดำเนินการ แน่นอนว่าสิ่งต่าง ๆ ที่ยืนคำตอบของคุณถูกต้องแม้ฉันจะมีความเข้าใจเกี่ยวกับภาษา
abstract static
: ฟังก์ชั่น X ที่จะ "ดำเนินการในประเภทรอง" ไม่สามารถ ที่ในเวลาเดียวกันจะ "ดำเนินการในชั้นเรียน" - เฉพาะในประเภทรอง ที่ซึ่งมันไม่เป็นนามธรรมอีกต่อไป
static
ไม่ได้หมายความว่า "ไม่ว่าง" - นั่นเป็นเพียงผลมาจาก Java ที่ไม่อนุญาตให้วิธีการแบบสแตติกเป็นนามธรรม มันหมายถึง "callable ในชั้นเรียน" (ควรจะหมายถึง "callable เฉพาะในชั้นเรียน" แต่นั่นเป็นปัญหาอื่น) หาก Java รองรับabstract static
วิธีที่ฉันคาดหวังว่าจะหมายถึงวิธีที่ 1) ต้องดำเนินการโดย subclasses และ 2) เป็นวิธีการเรียนของ subclass วิธีการบางอย่างก็ไม่สมเหตุสมผลเหมือนวิธีการของตัวอย่าง น่าเสียดายที่ Java ไม่อนุญาตให้คุณระบุว่าเมื่อสร้างคลาสฐานนามธรรม (หรืออินเทอร์เฟซ)
การออกแบบภาษาไม่ดี มันจะมีประสิทธิภาพมากขึ้นในการเรียกใช้วิธีนามธรรมคงที่โดยตรงมากกว่าการสร้างตัวอย่างเพียงแค่ใช้วิธีนามธรรมนั้น จริงโดยเฉพาะอย่างยิ่งเมื่อใช้คลาสนามธรรมเป็นวิธีแก้ปัญหาสำหรับ enum ไม่สามารถขยายซึ่งเป็นอีกตัวอย่างการออกแบบที่ไม่ดี หวังว่าพวกเขาจะแก้ไขข้อ จำกัด เหล่านั้นในรุ่นถัดไป
static
ตัวเองอยู่แล้วละเมิด ....
คุณไม่สามารถแทนที่เมธอดสแตติกได้ดังนั้นการทำให้เป็นนามธรรมจะไม่มีความหมาย ยิ่งไปกว่านั้นวิธีการคงที่ในคลาสนามธรรมจะเป็นของคลาสนั้นไม่ใช่คลาสที่แทนที่ดังนั้นจึงไม่สามารถใช้งานได้
การเพิ่มความคิดเห็นabstract
ไปยังเมธอดบ่งชี้ว่าเมธอดต้องถูกแทนที่ในคลาสย่อย
ใน Java เป็นstatic
สมาชิก (วิธีการหรือสาขา) ไม่สามารถแทนที่โดย subclasses (นี้ไม่จำเป็นต้องเป็นจริงในภาษาเชิงวัตถุอื่นดู SmallTalk.) พบstatic
สมาชิกอาจจะซ่อนอยู่แต่ที่เป็นพื้นฐานที่แตกต่างกว่าแทนที่
เนื่องจากสมาชิกแบบสแตติกไม่สามารถ overriden ในคลาสย่อยได้abstract
คำอธิบายประกอบจึงไม่สามารถใช้ได้กับพวกเขา
ในขณะที่ภาษาอื่นรองรับการสืบทอดแบบคงที่เช่นเดียวกับการสืบทอดอินสแตนซ์ จากมุมมองของไวยากรณ์ภาษาเหล่านั้นมักจะต้องการชื่อคลาสที่จะรวมอยู่ในคำสั่ง ตัวอย่างเช่นใน Java สมมติว่าคุณกำลังเขียนโค้ดใน ClassA นี่เป็นข้อความสั่งที่เทียบเท่ากัน (หาก methodA () เป็นวิธีคงที่และไม่มีวิธีอินสแตนซ์ที่มีลายเซ็นเดียวกัน):
ClassA.methodA();
และ
methodA();
ใน SmallTalk ชื่อคลาสนั้นไม่จำเป็นดังนั้นไวยากรณ์คือ (โปรดทราบว่า SmallTalk ไม่ได้ใช้. เพื่อแยก "subject" และ "verb" แต่ใช้แทนเป็นเทอร์มิเนล statemend):
ClassA methodA.
เนื่องจากชื่อคลาสจำเป็นต้องมีเสมอ "รุ่น" ของวิธีการที่ถูกต้องสามารถกำหนดได้เสมอโดยการข้ามผ่านลำดับชั้นของคลาส สำหรับสิ่งที่มีค่าฉันจะพลาดการstatic
รับมรดกเป็นครั้งคราวและถูกกัดโดยขาดการสืบทอดแบบคงที่ใน Java เมื่อฉันเริ่มต้นด้วย นอกจากนี้ SmallTalk จะพิมพ์ด้วยเป็ด (ดังนั้นจึงไม่สนับสนุนการทำสัญญาโดยโปรแกรม) ดังนั้นจึงไม่มีการabstract
แก้ไขสำหรับสมาชิกของคลาส
ฉันยังถามคำถามเดียวกันนี่คือเหตุผล
ตั้งแต่ชั้นนามธรรมพูดว่ามันจะไม่ให้การดำเนินการและอนุญาตให้ subclass เพื่อให้มัน
ดังนั้นซับคลาสต้องแทนที่เมธอดของ Superclass
กฎข้อที่ 1 - วิธีการแบบคงที่ไม่สามารถเขียนทับได้
เนื่องจากสมาชิกและวิธีการแบบคงที่เป็นองค์ประกอบเวลารวบรวมนั่นคือเหตุผลที่การโอเวอร์โหลด (Polile time Polymorphism) ของวิธีการแบบสแตติกได้รับอนุญาตให้ใช้งานมากกว่าการแทนที่ (Runtime Polymorphism)
ดังนั้นพวกเขาไม่สามารถเป็นนามธรรมได้
ไม่มีสิ่งใดเหมือนนามธรรมแบบคงที่ <--- ไม่อนุญาตใน Java Universe
abstract static
เห็นstackoverflow.com/questions/370962/... เหตุผลที่แท้จริงว่าทำไม Java ไม่อนุญาตให้มีวิธีการแบบคงที่จะแทนที่เป็นเพราะ Java ไม่อนุญาตให้มีวิธีการแบบคงที่จะแทนที่
foo(String)
ไม่เหมือนกับfoo(Integer)
- นั่นคือทั้งหมดที่มันเป็น
นี่คือการออกแบบภาษาที่แย่มากและไม่มีเหตุผลว่าทำไมถึงเป็นไปไม่ได้
ในความเป็นจริงนี่คือการดำเนินการเกี่ยวกับวิธีการที่สามารถทำได้ในJAVA :
public class Main {
public static void main(String[] args) {
// This is done once in your application, usually at startup
Request.setRequest(new RequestImplementationOther());
Request.doSomething();
}
public static final class RequestImplementationDefault extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something AAAAAA");
}
}
public static final class RequestImplementaionOther extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something BBBBBB");
}
}
// Static methods in here can be overriden
public static abstract class Request {
abstract void doSomethingImpl();
// Static method
public static void doSomething() {
getRequest().doSomethingImpl();
}
private static Request request;
private static Request getRequest() {
// If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too.
if ( request == null ) {
return request = new RequestImplementationDefault();
}
return request;
}
public static Request setRequest(Request r){
return request = r;
}
}
}
================= ตัวอย่างเก่าด้านล่าง =================
ค้นหา getRequest และสามารถเรียกใช้ getRequestImpl ... setInstance เพื่อปรับเปลี่ยนการใช้งานก่อนที่จะทำการโทร
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author Mo. Joseph
* @date 16 mar 2012
**/
public abstract class Core {
// ---------------------------------------------------------------
private static Core singleton;
private static Core getInstance() {
if ( singleton == null )
setInstance( new Core.CoreDefaultImpl() ); // See bottom for CoreDefaultImpl
return singleton;
}
public static void setInstance(Core core) {
Core.singleton = core;
}
// ---------------------------------------------------------------
// Static public method
public static HttpServletRequest getRequest() {
return getInstance().getRequestImpl();
}
// A new implementation would override this one and call setInstance above with that implementation instance
protected abstract HttpServletRequest getRequestImpl();
// ============================ CLASSES =================================
// ======================================================================
// == Two example implementations, to alter getRequest() call behaviour
// == getInstance() have to be called in all static methods for this to work
// == static method getRequest is altered through implementation of getRequestImpl
// ======================================================================
/** Static inner class CoreDefaultImpl */
public static class CoreDefaultImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
/** Static inner class CoreTestImpl : Alternative implementation */
public static class CoreTestImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return new MockedRequest();
}
}
}
ใช้ดังต่อไปนี้:
static {
Core.setSingleton(new Core.CoreDefaultImpl());
// Or
Core.setSingleton(new Core.CoreTestImpl());
// Later in the application you might use
Core.getRequest();
}
abstract static
วิธีการตามที่ถามในคำถามและคุณเขียนเป็นตัวหนาสามารถทำได้ในJAVA นี่เป็นการเข้าใจผิดอย่างสมบูรณ์
วิธีนามธรรมถูกกำหนดไว้เท่านั้นเพื่อให้สามารถแทนที่ในคลาสย่อย อย่างไรก็ตามวิธีการคงที่ไม่สามารถแทนที่ ดังนั้นจึงเป็นข้อผิดพลาดในการคอมไพล์เพื่อให้มีวิธีนามธรรมแบบคงที่
ตอนนี้คำถามต่อไปคือเหตุผลที่ว่าทำไมวิธีการแบบคงที่ไม่สามารถเขียนทับได้?
เป็นเพราะวิธีการคงที่เป็นของชั้นเรียนเฉพาะและไม่ได้เป็นตัวอย่าง หากคุณพยายามแทนที่เมธอดสแตติกคุณจะไม่ได้รับการรวบรวมหรือข้อผิดพลาดรันไทม์ แต่คอมไพเลอร์จะซ่อนเมธอดแบบคงที่ของซูเปอร์คลาส
this
วิธีการแบบคงที่โดยความหมายไม่จำเป็นต้องรู้ ดังนั้นจึงไม่สามารถเป็นวิธีเสมือน (ที่มีการโอเวอร์โหลดตามข้อมูลคลาสย่อยแบบไดนามิกที่มีให้ผ่านthis
); แทนวิธีคงที่เกินพิกัดจะขึ้นอยู่กับข้อมูลที่มีอยู่ในเวลารวบรวมเท่านั้น (ซึ่งหมายความว่า: เมื่อคุณอ้างถึงวิธีการคงที่ของซูเปอร์คลาสคุณจะเรียกว่าวิธีการซูเปอร์คลาส แต่ไม่เคยเป็นวิธีการคลาสย่อย)
ตามนี้วิธีคงที่นามธรรมจะค่อนข้างไร้ประโยชน์เพราะคุณจะไม่เคยมีการอ้างอิงแทนโดยร่างกายที่กำหนดบางอย่าง
ฉันเห็นว่ามีคำตอบ god-zillion แล้ว แต่ฉันไม่เห็นวิธีแก้ปัญหาการปฏิบัติใด ๆ แน่นอนว่านี่เป็นปัญหาที่แท้จริงและไม่มีเหตุผลที่ดีสำหรับการยกเว้นไวยากรณ์นี้ใน Java เนื่องจากคำถามเดิมไม่มีบริบทที่อาจจำเป็นฉันจึงให้ทั้งบริบทและวิธีการแก้ไข:
สมมติว่าคุณมีวิธีการคงที่ในกลุ่มของชั้นเรียนที่เหมือนกัน เมธอดเหล่านี้เรียกเมธอดสแตติกที่เป็นคลาสเฉพาะ:
class C1 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C1
}
}
class C2 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C2
}
}
doWork()
วิธีการในC1
และC2
เหมือนกัน อาจมี calsses เหล่านี้จำนวนมาก: C3
C4
ฯลฯ หากstatic abstract
ได้รับอนุญาตคุณต้องกำจัดรหัสซ้ำโดยทำสิ่งต่อไปนี้:
abstract class C {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
static abstract void doMoreWork(int k);
}
class C1 extends C {
private static void doMoreWork(int k) {
// code for class C1
}
}
class C2 extends C {
private static void doMoreWork(int k) {
// code for class C2
}
}
แต่สิ่งนี้จะไม่รวบรวมเพราะstatic abstract
ไม่อนุญาตให้รวมกัน อย่างไรก็ตามสิ่งนี้สามารถหลีกเลี่ยงได้ด้วยการstatic class
สร้างซึ่งได้รับอนุญาต:
abstract class C {
void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
abstract void doMoreWork(int k);
}
class C1 {
private static final C c = new C(){
@Override void doMoreWork(int k) {
System.out.println("code for C1");
}
};
public static void doWork() {
c.doWork();
}
}
class C2 {
private static final C c = new C() {
@Override void doMoreWork(int k) {
System.out.println("code for C2");
}
};
public static void doWork() {
c.doWork();
}
}
ด้วยวิธีนี้รหัสเดียวที่ซ้ำกันคือ
public static void doWork() {
c.doWork();
}
C1.doWork()
หรือC2.doWork()
แต่คุณไม่สามารถโทรC.doWork()
ได้ นอกจากนี้ในตัวอย่างที่คุณให้ไว้ซึ่งไม่สามารถใช้งานได้ถ้าสมมติว่าได้รับอนุญาตแล้วชั้นเรียนจะC
หาวิธีการนำไปปฏิบัติdoMoreWork()
อย่างไร ในที่สุดฉันจะเรียกรหัสบริบทของคุณการออกแบบที่ไม่ดี ทำไม? C
เพียงเพราะคุณได้สร้างฟังก์ชั่นที่แยกต่างหากสำหรับรหัสที่เป็นเอกลักษณ์แทนการสร้างฟังก์ชั่นสำหรับรหัสที่เป็นปกติแล้วการใช้ฟังก์ชั่นคงที่ในชั้นเรียน มันง่ายกว่า !!!
สมมติว่ามีสองคลาสParent
และChild
. เป็นParent
abstract
การประกาศมีดังนี้:
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
ซึ่งหมายความว่าอินสแตนซ์ใด ๆ ของParent
ต้องระบุวิธีrun()
การดำเนินการ
แต่สมมติว่าตอนนี้ไม่ได้Parent
abstract
class Parent {
static void run() {}
}
ซึ่งหมายความว่าParent.run()
จะดำเนินการวิธีการคงที่
คำจำกัดความของabstract
วิธีการคือ "วิธีการที่ประกาศ แต่ไม่ได้ใช้" ซึ่งหมายความว่าจะไม่ส่งคืนสิ่งใดเอง
คำจำกัดความของstatic
วิธีการคือ "วิธีการที่ส่งกลับค่าเดียวกันสำหรับพารามิเตอร์เดียวกันโดยไม่คำนึงถึงอินสแตนซ์ที่มันถูกเรียกว่า"
abstract
ค่าตอบแทนวิธีการจะมีการเปลี่ยนแปลงการเปลี่ยนแปลงเช่น static
วิธีจะไม่ static abstract
วิธีสวยมากวิธีการที่ค่าตอบแทนเป็นค่าคงที่ แต่ไม่กลับอะไร นี่คือความขัดแย้งทางตรรกะ
นอกจากนี้ยังมีเหตุผลไม่มากสำหรับstatic abstract
วิธีการ
คลาสนามธรรมไม่สามารถมีวิธีแบบสแตติกได้เนื่องจากมีการทำนามธรรมเพื่อให้บรรลุการเชื่อมโยงแบบไดนามิกในขณะที่วิธีการแบบคงที่ถูกผูกไว้กับการทำงานของพวกเขาวิธีการแบบคงที่หมายถึงพฤติกรรมที่ไม่ขึ้นอยู่กับตัวแปรอินสแตนซ์ วิธีการคงที่เป็นของชั้นเรียนและไม่วัตถุ พวกเขาจะถูกเก็บไว้ในพื้นที่หน่วยความจำที่รู้จักกันเป็น PERMGEN จากที่มันถูกใช้ร่วมกับทุกวัตถุ วิธีการในชั้นนามธรรมจะผูกกับการทำงานของพวกเขาแบบไดนามิก
ประกาศวิธีการเป็นstatic
วิธีการที่เราสามารถเรียกวิธีการว่าด้วยชื่อชั้นและถ้าระดับที่เป็นabstract
เช่นกันมันทำให้รู้สึกไม่ที่จะเรียกมันขณะที่มันไม่ได้มีตัวใดและด้วยเหตุนี้เราไม่สามารถประกาศวิธีการที่ทั้งสองเป็นและstatic
abstract
เนื่องจากเมธอด abstract เป็นของคลาสและไม่สามารถถูกแทนที่โดยคลาสที่นำไปใช้แม้ว่าจะมีเมธอดแบบสแตติกที่มีลายเซ็นเหมือนกันมันจะซ่อนเมธอดไม่แทนที่มัน ดังนั้นจึงไม่มีสาระสำคัญที่จะประกาศวิธีนามธรรมเป็นแบบคงที่ไม่เคยได้รับร่างกายดังนั้นข้อผิดพลาดเวลารวบรวม
วิธีการคงที่สามารถเรียกได้โดยไม่มีตัวอย่างของชั้นเรียน ในตัวอย่างของคุณคุณสามารถโทร foo.bar2 () แต่ไม่ใช่ foo.bar () เพราะสำหรับแถบที่คุณต้องการอินสแตนซ์ รหัสต่อไปนี้จะใช้งานได้:
foo var = new ImplementsFoo();
var.bar();
หากคุณเรียกใช้วิธีการคงที่มันจะถูกดำเนินการเสมอรหัสเดียวกัน ในตัวอย่างข้างต้นแม้ว่าคุณจะกำหนด bar2 ใหม่ใน ImplementsFoo การเรียกไปที่ var.bar2 () จะเรียกใช้งาน foo.bar2 ()
ถ้า bar2 ไม่มีการนำไปใช้ (นั่นคือความหมายเชิงนามธรรม) คุณสามารถเรียกใช้เมธอดได้โดยไม่ต้องติดตั้ง นั่นเป็นอันตรายมาก
ฉันเชื่อว่าฉันได้พบคำตอบสำหรับคำถามนี้ในรูปแบบของวิธีการอินเทอร์เฟซของ (ซึ่งทำงานเช่นวิธีนามธรรมในระดับผู้ปกครอง) ไม่สามารถคงที่ นี่คือคำตอบแบบเต็ม (ไม่ใช่ของฉัน)
โดยทั่วไปวิธีการคงที่สามารถถูกผูกไว้ในเวลารวบรวมตั้งแต่การเรียกพวกเขาคุณต้องระบุชั้นเรียน ซึ่งแตกต่างจากวิธีการแบบอินสแตนซ์ซึ่งคลาสของการอ้างอิงที่คุณกำลังเรียกวิธีอาจไม่เป็นที่รู้จักในเวลารวบรวม
หากคุณกำลังเรียกใช้เมธอดแบบสแตติกคุณจะทราบคลาสที่ใช้งานหรือคลาสย่อยโดยตรงของคลาสนั้น หากคุณกำหนด
abstract class Foo {
abstract static void bar();
}
class Foo2 {
@Override
static void bar() {}
}
แล้วใด ๆโทรเป็นสิ่งผิดกฎหมายอย่างเห็นได้ชัดและคุณก็จะใช้Foo.bar();
Foo2.bar();
เมื่อคำนึงถึงสิ่งนี้จุดประสงค์เพียงอย่างเดียวของวิธีนามธรรมแบบสแตติกคือการบังคับใช้คลาสย่อยเพื่อใช้วิธีดังกล่าว ในขั้นต้นคุณอาจคิดว่านี่เป็นสิ่งที่ผิดมาก แต่ถ้าคุณมีพารามิเตอร์ประเภททั่วไป<E extends MySuperClass>
มันจะดีที่จะรับประกันผ่านอินเตอร์เฟซที่สามารถE
.doSomething()
โปรดทราบว่าเนื่องจากประเภทการลบข้อมูลทั่วไปมีอยู่ในเวลารวบรวมเท่านั้น
ดังนั้นมันจะมีประโยชน์หรือไม่ ใช่และนั่นอาจเป็นเหตุผลว่าทำไม Java 8 จึงอนุญาตให้ใช้เมธอดแบบคงที่ในส่วนต่อประสาน ทำไมไม่ใช้วิธีแบบคงที่นามธรรมที่มีการใช้งานเริ่มต้นในชั้นเรียน? เพียงเพราะวิธีนามธรรมที่มีการใช้งานเริ่มต้นเป็นจริงวิธีการที่เป็นรูปธรรม
ทำไมไม่ใช้วิธีแบบนามธรรม / ส่วนต่อประสานที่ไม่มีการใช้งานเริ่มต้น เห็นได้ชัดว่าเป็นเพราะวิธีการที่จาวาระบุว่าการบล็อกโค้ดนั้นจะต้องดำเนินการอย่างไร (ส่วนแรกของคำตอบของฉัน)
เนื่องจากคลาสนามธรรมเป็นแนวคิด OOPS และสมาชิกแบบสแตติกไม่ได้เป็นส่วนหนึ่งของ OOPS ....
ตอนนี้สิ่งที่เราสามารถประกาศวิธีการแบบคงที่สมบูรณ์ในส่วนต่อประสานและเราสามารถดำเนินการส่วนต่อประสานโดยประกาศวิธีหลักภายในอินเทอร์เฟซ
interface Demo
{
public static void main(String [] args) {
System.out.println("I am from interface");
}
}
แนวคิดของการมีวิธีนามธรรมแบบคงที่คือคุณไม่สามารถใช้คลาสนามธรรมเฉพาะนั้นได้โดยตรงสำหรับวิธีนั้น แต่มีเพียงอนุพันธ์แรกเท่านั้นที่ได้รับอนุญาตให้ใช้วิธีแบบคงที่นั้น (หรือสำหรับ generics: คลาสจริงของสามัญคุณ ใช้).
ด้วยวิธีนี้คุณสามารถสร้างตัวอย่างคลาสนามธรรม sortableObject หรืออินเทอร์เฟซด้วย (อัตโนมัติ -) วิธีคงที่นามธรรมซึ่งกำหนดพารามิเตอร์ของตัวเลือกการจัดเรียง:
public interface SortableObject {
public [abstract] static String [] getSortableTypes();
public String getSortableValueByType(String type);
}
ตอนนี้คุณสามารถกำหนดวัตถุที่สามารถเรียงลำดับได้ซึ่งสามารถจัดเรียงตามประเภทหลักที่เหมือนกันสำหรับวัตถุเหล่านี้ทั้งหมด:
public class MyDataObject implements SortableObject {
final static String [] SORT_TYPES = {
"Name","Date of Birth"
}
static long newDataIndex = 0L ;
String fullName ;
String sortableDate ;
long dataIndex = -1L ;
public MyDataObject(String name, int year, int month, int day) {
if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
this.fullName = name ;
this.sortableDate = MyUtils.createSortableDate(year,month,day);
this.dataIndex = MyDataObject.newDataIndex++ ;
}
public String toString() {
return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
}
// override SortableObject
public static String [] getSortableTypes() { return SORT_TYPES ; }
public String getSortableValueByType(String type) {
int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
switch(index) {
case 0: return this.name ;
case 1: return this.sortableDate ;
}
return toString(); // in the order they were created when compared
}
}
ตอนนี้คุณสามารถสร้าง
public class SortableList<T extends SortableObject>
ที่สามารถดึงประเภทสร้างเมนูป๊อปอัพเพื่อเลือกประเภทที่จะเรียงลำดับและใช้รายการโดยรับข้อมูลจากประเภทนั้นรวมทั้ง hainv ฟังก์ชั่นเพิ่มที่เมื่อเลือกประเภทการเรียงสามารถอัตโนมัติ - เรียงรายการใหม่ ๆ โปรดทราบว่าอินสแตนซ์ของ SortableList สามารถเข้าถึงวิธีการคงที่ของ "T" โดยตรง:
String [] MenuItems = T.getSortableTypes();
ปัญหาเกี่ยวกับการใช้อินสแตนซ์คือ SortableList อาจยังไม่มีไอเท็ม แต่จำเป็นต้องมีการจัดเรียงที่ต้องการอยู่แล้ว
Cheerio, Olaf
ก่อนอื่นประเด็นสำคัญเกี่ยวกับคลาสนามธรรม - คลาสนามธรรมไม่สามารถสร้างอินสแตนซ์ได้ (ดูวิกิ ) ดังนั้นคุณไม่สามารถสร้างใด ๆตัวอย่างของระดับนามธรรม
ตอนนี้วิธีที่จาวาเกี่ยวข้องกับวิธีการคงที่คือการแบ่งปันวิธีการกับอินสแตนซ์ทั้งหมดของชั้นเรียนที่
ดังนั้นหากคุณไม่สามารถยกตัวอย่างคลาสได้คลาสนั้นจะไม่มีเมธอดสแตติกแบบนามธรรมเนื่องจากเมธอดแบบนามธรรมจะถูกขยายออกไป
ความเจริญ
ตามเอกสาร Java :
วิธีการคงที่เป็นวิธีการที่เกี่ยวข้องกับชั้นเรียนที่มีการกำหนดมากกว่าที่จะมีวัตถุใด ๆ ทุกอินสแตนซ์ของคลาสแบ่งปันวิธีการแบบคงที่
ใน Java 8 พร้อมกับเมธอดดีฟอลต์เมธอดสแตติกจะอนุญาตในอินเตอร์เฟส สิ่งนี้ทำให้ง่ายขึ้นสำหรับเราในการจัดระเบียบวิธีการช่วยเหลือในห้องสมุดของเรา เราสามารถเก็บวิธีการแบบคงที่เฉพาะกับอินเทอร์เฟซในอินเทอร์เฟซเดียวกันมากกว่าในคลาสแยกต่างหาก
ตัวอย่างที่ดีของสิ่งนี้คือ:
list.sort(ordering);
แทน
Collections.sort(list, ordering);
ตัวอย่างของการใช้วิธีการคงที่อีกอย่างหนึ่งก็คือในdocเอง:
public interface TimeClient {
// ...
static public ZoneId getZoneId (String zoneString) {
try {
return ZoneId.of(zoneString);
} catch (DateTimeException e) {
System.err.println("Invalid time zone: " + zoneString +
"; using default time zone instead.");
return ZoneId.systemDefault();
}
}
default public ZonedDateTime getZonedDateTime(String zoneString) {
return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
}
}
เพราะ 'นามธรรม' หมายถึงวิธีการที่มีขึ้นเพื่อแทนที่และหนึ่งไม่สามารถแทนที่วิธีการ 'คงที่'
วิธีการปกติสามารถเป็นนามธรรมได้เมื่อพวกเขาตั้งใจจะถูกแทนที่โดย subclasses และจัดให้มีฟังก์ชั่น ลองนึกภาพว่าคลาสFoo
นั้นขยายออกไปBar1, Bar2, Bar3
ดังนั้นแต่ละคลาสจะมีคลาสนามธรรมของตัวเองตามความต้องการ
ตอนนี้วิธีการคงที่ตามคำนิยามอยู่ในชั้นเรียนพวกเขาไม่มีอะไรจะทำอย่างไรกับวัตถุของชั้นเรียนหรือวัตถุของชั้นย่อยของมัน พวกเขาไม่จำเป็นต้องมีอยู่พวกเขาสามารถใช้งานได้โดยไม่ต้องทำให้ชั้นเรียนเป็นอินสแตนซ์ ดังนั้นพวกเขาจำเป็นต้องพร้อมใช้งานและไม่สามารถพึ่งพาคลาสย่อยเพื่อเพิ่มฟังก์ชันการทำงานให้กับพวกเขา
เพราะนามธรรมเป็นคำหลักที่ใช้กับวิธีการนามธรรมไม่ได้ระบุเนื้อหา และถ้าเราพูดถึงคำหลักคงที่มันเป็นพื้นที่ชั้นเรียน
เพราะถ้าคุณใช้สมาชิกแบบสแตติกหรือตัวแปรแบบสแตติกในคลาสมันจะโหลด ณ เวลาที่โหลดคลาส
คุณสามารถทำได้ด้วยส่วนต่อประสานใน Java 8
นี่คือเอกสารเกี่ยวกับมันอย่างเป็นทางการ:
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
เพราะถ้าคลาสขยายคลาสนามธรรมแล้วมันจะต้องแทนที่เมธอด abstract และนั่นเป็นสิ่งที่จำเป็น และเนื่องจากวิธีการแบบคงที่เป็นวิธีการเรียนที่ได้รับการแก้ไขในเวลารวบรวมในขณะที่วิธีการแทนที่เป็นวิธีการอินสแตนซ์ได้รับการแก้ไขในขณะทำงานและต่อไปนี้ความแตกต่างแบบไดนามิก