为什么不可能重写静态方法?
如果可能,请举例说明。
为什么不可能重写静态方法?
如果可能,请举例说明。
当前回答
Here is a simple explanation. A static method is associated with a class while an instance method is associated with a particular object. Overrides allow calling the different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but the class itself in the first place. So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.
其他回答
现在看到上面的答案,每个人都知道我们不能重写静态方法,但不应该误解从子类访问静态方法的概念。
我们可以通过子类引用访问超类的静态方法,如果这个静态方法没有被子类中定义的新静态方法所隐藏。
例如,请参见下面的代码:-
public class StaticMethodsHiding {
public static void main(String[] args) {
SubClass.hello();
}
}
class SuperClass {
static void hello(){
System.out.println("SuperClass saying Hello");
}
}
class SubClass extends SuperClass {
// static void hello() {
// System.out.println("SubClass Hello");
// }
}
输出:
SuperClass saying Hello
关于在子类中隐藏静态方法的细节,请参阅Java oracle文档并搜索你可以在子类中做什么。
谢谢
我个人认为这是Java设计中的一个缺陷。是的,是的,我理解非静态方法附加到实例,而静态方法附加到类,等等。不过,考虑下面的代码:
public class RegularEmployee {
private BigDecimal salary;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(getBonusMultiplier());
}
/* ... presumably lots of other code ... */
}
public class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
这段代码不能像您期望的那样工作。也就是说,特殊员工和普通员工一样有2%的奖金。但如果你去掉了“静态”,那么SpecialEmployee就能得到3%的奖金。
(不可否认,这个例子的编码风格很差,因为在现实生活中,你可能希望奖励乘数在数据库的某个地方,而不是硬编码。但这只是因为我不想用大量与主题无关的代码使示例陷入困境。)
在我看来,您可能想要使getBonusMultiplier成为静态的,这似乎很合理。也许您希望能够显示所有员工类别的奖金乘数,而不需要在每个类别中有一个员工实例。搜索这样的例子有什么意义呢?如果我们正在创建一个新的员工类别,并且还没有任何员工分配给它,该怎么办?这在逻辑上是一个静态函数。
但这并不奏效。
是的,是的,我可以想出很多方法来重写上面的代码,让它工作。我的观点不是它产生了一个无法解决的问题,而是它为粗心的程序员制造了一个陷阱,因为这种语言的行为不像我认为一个理性的人所期望的那样。
也许如果我试着为OOP语言编写一个编译器,我很快就会明白为什么实现它以覆盖静态函数是困难的或不可能的。
或许有一些很好的理由来解释为什么Java会这样做。有人能指出这种行为的好处吗,这种行为能让一些问题变得更简单吗?我的意思是,不要只是把我指给Java语言规范,然后说“看,这是它如何行为的文档”。我知道。但是,它为什么会有这样的表现,有一个很好的理由吗?(除了明显的“让它正常工作太难了”……)
更新
@VicKirk: If you mean that this is "bad design" because it doesn't fit how Java handles statics, my reply is, "Well, duh, of course." As I said in my original post, it doesn't work. But if you mean that it is bad design in the sense that there would be something fundamentally wrong with a language where this worked, i.e. where statics could be overridden just like virtual functions, that this would somehow introduce an ambiguity or it would be impossible to implement efficiently or some such, I reply, "Why? What's wrong with the concept?"
I think the example I give is a very natural thing to want to do. I have a class that has a function that does not depend on any instance data, and which I might very reasonably want to call independent of an instance, as well as wanting to call from within an instance method. Why should this not work? I've run into this situation a fair number of times over the years. In practice I get around it by making the function virtual, and then creating a static method whose only purpose in life is to be a static method that passes the call on to the virtual method with a dummy instance. That seems like a very roundabout way to get there.
重写是为实例成员保留的,以支持多态行为。静态类成员不属于特定实例。相反,静态成员属于类,因此不支持重写,因为子类只继承受保护和公共实例成员,而不继承静态成员。您可能希望定义一个接口,并研究工厂和/或策略设计模式,以评估替代方法。
静态方法、变量、块或嵌套类属于整个类而不是对象。
Java中的方法用于公开对象/类的行为。在这里,由于方法是静态的(即静态方法仅用于表示类的行为),改变/覆盖整个类的行为将违反面向对象编程的基本支柱之一,即高内聚。(记住构造函数在Java中是一种特殊的方法。)
高内聚性——一个类应该只有一个角色。例如:car类应该只生成汽车对象,而不生成自行车、卡车、飞机等。但是Car类可能有一些只属于它自己的特性(行为)。
因此,在设计java编程语言时。语言设计者认为,只有通过使方法本质上是静态的,才能允许开发人员保留类的某些行为。
下面的代码尝试覆盖静态方法,但不会遇到任何编译错误。
public class Vehicle {
static int VIN;
public static int getVehileNumber() {
return VIN;
}}
class Car extends Vehicle {
static int carNumber;
public static int getVehileNumber() {
return carNumber;
}}
这是因为,在这里我们没有重写一个方法,而只是重新声明它。Java允许重新声明一个方法(静态/非静态)。
从Car类的getVehileNumber()方法中删除静态关键字将导致编译错误,因为,我们正在尝试改变只属于Vehicle类的静态方法的功能。
此外,如果getVehileNumber()被声明为final,那么代码将无法编译,因为final关键字限制程序员重新声明方法。
public static final int getVehileNumber() {
return VIN; }
总的来说,这取决于软件设计人员在哪里使用静态方法。 我个人更喜欢使用静态方法来执行某些操作,而不需要创建类的任何实例。第二,对外界隐藏一个类的行为。
Here is a simple explanation. A static method is associated with a class while an instance method is associated with a particular object. Overrides allow calling the different implementation of the overridden methods associated with the particular object. So it is counter-intuitive to override static method which is not even associated with objects but the class itself in the first place. So static methods cannot be overridden based on what object is calling it, it will always be associated with the class where it was created.