hha*_*fez 572 java abstract-class static-methods
问题是在Java中为什么我不能定义一个抽象的静态方法?例如
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*lak 544
因为"abstract"意味着:"实现没有功能","静态"意味着:"即使你没有对象实例也有功能".这是一个合乎逻辑的矛盾.
小智 310
语言设计不佳.直接调用静态抽象方法比仅使用该抽象方法创建实例会更有效.当使用抽象类作为枚举无法扩展的变通方法时尤其如此,这是另一个糟糕的设计示例.希望他们在下一个版本中解决这些限制.
Gar*_*ryF 143
您不能覆盖静态方法,因此将其抽象化将毫无意义.此外,在抽象类的静态方法将属于这个阶层,而不是覆盖类,因此无法使用反正.
Jar*_*red 70
abstract方法的注释表明该方法必须在子类中重写.
在Java中,static子类不能覆盖成员(方法或字段)(在其他面向对象的语言中不一定如此,请参阅SmallTalk.)static成员可能被隐藏,但这与被覆盖的根本不同.
由于静态成员无法在子类中重写,abstract因此无法将注释应用于它们.
另外 - 其他语言确实支持静态继承,就像实例继承一样.从语法的角度来看,这些语言通常需要将类名包含在语句中.例如,在Java中,假设您在ClassA中编写代码,这些是等效语句(如果methodA()是静态方法,并且没有具有相同签名的实例方法):
ClassA.methodA();
Run Code Online (Sandbox Code Playgroud)
和
methodA();
Run Code Online (Sandbox Code Playgroud)
在SmallTalk中,类名不是可选的,因此语法是(请注意,SmallTalk不使用.来分隔"主题"和"动词",而是将其用作statemend终结符):
ClassA methodA.
Run Code Online (Sandbox Code Playgroud)
由于始终需要类名,因此始终可以通过遍历类层次结构来确定方法的正确"版本".对于它的价值,我偶尔会错过static继承,并且当我第一次开始使用Java时,由于缺乏静态继承而被咬了.另外,SmallTalk是鸭子类型(因此不支持逐个程序.)因此,它没有abstract类成员的修饰符.
ans*_*tta 14
我也问了同样的问题,这就是原因
从Abstract类开始说,它不会给出实现并允许子类给它
所以Subclass必须覆盖Superclass的方法,
RULE NO 1 - 无法覆盖静态方法
因为静态成员和方法是编译时元素,这就是为什么允许静态方法的重载(编译时多态)而不是覆盖(运行时多态)
所以,他们不能抽象.
没有抽象静态 <--- Java Universe中不允许的东西
mom*_*omo 12
这是一个糟糕的语言设计,并没有理由为什么它不可能.
事实上,这里是如何实现CAN在做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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
=================下面的旧例子=================
查找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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
仅定义抽象方法,以便可以在子类中重写它.但是,无法覆盖静态方法.因此,具有抽象的静态方法是编译时错误.
现在接下来的问题是为什么静态方法不能被覆盖?
这是因为静态方法属于特定类而不属于其实例.如果您尝试覆盖静态方法,则不会得到任何编译或运行时错误,但编译器只会隐藏超类的静态方法.
根据定义,静态方法不需要知道this. 因此,它不能是虚方法(根据通过 可用的动态子类信息重载this);相反,静态方法重载完全基于编译时可用的信息(这意味着:一旦您引用超类的静态方法,您即调用超类方法,而不是子类方法)。
据此,抽象静态方法将毫无用处,因为您永远不会将其引用替换为某个已定义的主体。