接口中的属性/成员variables?
我想知道有没有什么方法可以让实现者声明对象句柄/原语,就像他们对方法所做的那样。 例如:
public interface Rectangle { int height = 0; int width = 0; public int getHeight(); public int getWidth(); public void setHeight(int height); public void setWidth(int width); } public class Tile implements Rectangle{ @Override public int getHeight() { return 0; } @Override public int getWidth() { return 0; } @Override public void setHeight(int height) { } @Override public void setWidth(int width) { } }
在上面的方法中,我们如何强迫Tile类使用接口声明高度和宽度属性? 出于某种原因,我希望只用接口来做!
我最初想到inheritance使用它。 但事情是我必须处理3class。
- 长方形
- 瓦
- JLabel的!
class Tile extends JLabel implements Rectangle {}
会工作。!
但
class Tile extends JLabel extends Rectangle {}
不要!
接口的要点是指定公共API。 一个接口没有状态。 你创build的任何variables都是常量(所以要小心在接口中创build可变对象)。
基本上一个接口这里说的是所有实现它的类必须支持的方法。 如果Java的创build者在接口中不允许使用常量,但是现在已经太晚(现在有些情况下常量在接口中是合理的),那么可能会更好。
因为你只是指定要实现什么方法,所以没有状态的概念(没有实例variables)。 如果你想要求每个类都有一个特定的variables,你需要使用一个抽象类。
最后,一般来说,你应该不使用公共variables,所以把variables放入界面的想法是一个不好的主意。
简短的回答 – 你不能做你想做的,因为它在Java中是“错误的”。
编辑:
class Tile implements Rectangle { private int height; private int width; @Override public int getHeight() { return height; } @Override public int getWidth() { return width; } @Override public void setHeight(int h) { height = h; } @Override public void setWidth(int w) { width = w; } }
一个替代版本将是:
abstract class AbstractRectangle implements Rectangle { private int height; private int width; @Override public int getHeight() { return height; } @Override public int getWidth() { return width; } @Override public void setHeight(int h) { height = h; } @Override public void setWidth(int w) { width = w; } } class Tile extends AbstractRectangle { }
你只能用抽象类来做,而不能用接口。
将Rectangle
声明为abstract class
而不是interface
并将必须由子类实现的方法声明为public abstract
。 然后,类Tile
inheritance类Rectangle
并且必须从Rectangle
实现抽象方法。
接口不能要求定义实例variables – 只有方法。
( variables可以在接口中定义 ,但是它们不像预期的那样行为:它们被视为final static
。)
快乐的编码。
Java 8引入了默认的接口方法,您可以使用这些接口的方法。 根据OOP,接口应作为两个系统/各方之间的合同。
但是,我仍然发现了一种在界面中实现存储属性的方法。 我承认这有点不好实现。
import java.util.Map; import java.util.WeakHashMap; interface Rectangle { class Storage { private static final Map<Rectangle, Integer> heightMap = new WeakHashMap<>(); private static final Map<Rectangle, Integer> widthMap = new WeakHashMap<>(); } default public int getHeight() { return Storage.heightMap.get(this); } default public int getWidth() { return Storage.widthMap.get(this); } default public void setHeight(int height) { Storage.heightMap.put(this, height); } default public void setWidth(int width) { Storage.widthMap.put(this, width); } }
这个界面很丑。 为了存储简单的属性,它需要两个hashmaps,默认情况下每个hashmap默认创build16个条目。 另外,当真实对象被解除引用时,JVM还需要删除这个弱引用。
在Java中,你不能。 接口与方法和签名有关,它不需要处理对象的内部状态 – 这是一个实现问题。 这也是有意义的 – 我的意思是,仅仅因为某些属性存在,并不意味着它们必须被实施类使用。 getHeight实际上可以指向宽度variables(假设实现者是虐待者)。
(注意 – 所有语言都不是这样,ActionScript允许声明伪属性,我相信C#也是这样)
接口中的字段隐式地为public static final
。 (也有方法是隐式公开的,所以你可以删除public
关键字。)即使你使用抽象类而不是接口,我强烈build议使所有非常量(原始或不可变对象引用的public static final
)为private
。 更一般的“更喜欢组合inheritance” – Tile
不是一个Rectangle
(当然,你可以用“is-a”和“has-a”来玩文字游戏)。
汤姆说过一件重要的事情:
如果你使用has-a的概念,你可以避免这个问题。
实际上,如果不是使用extends和implements来定义两个属性,即矩形的一个types,即Tile
类中的JLabel
types之一,则可以将Rectangle
定义为接口或类。
此外,我通常会鼓励使用与has-a有关的接口,但是我想这会对你的情况有所帮助。 但是,您是唯一可以决定这一点的人(权衡灵活性/过度工程)。