有没有办法让所有派生类计算他们的实例?如何(用C++,C#,Java之一编写代码)?
想象一下,我可以访问根类(例如对象),并且每个其他类(直接或间接)派生自此类.我想要的是:
AnyDerivedClass.InstancesCount()
Run Code Online (Sandbox Code Playgroud)
问题是,必须跟踪静态变量中的计数,但是不可能将静态变量"注入"到基类的派生类中,这仅适用于成员变量.也就是说,我必须写下这样的东西:
class object
{
private static int count = 0;
protected object() { ++count; }
protected ~object() { --count; }
public static InstancesCount() { return count; }
};
class derived : object
{
private static int count = 0;
public derived() { ++count; }
public ~derived() { --count; }
public static InstancesCount() { return count; }
}
Run Code Online (Sandbox Code Playgroud)
这个功能显然是重复的,我不能把它放在基类中.注意有两种计算方法:如果有7个类的derived1实例和8个类的derived2实例,则有(a)15个对象实例或(b)0个对象实例.我不关心哪一个,因为我不能做任何事(使用合理的实用手段,例如想象100个类,其中一半在库中我无法修改).
当然,理论上可以创建(某些运行类型标识符)=> int count的映射,并使用基于丑陋,慢,(运行时类型)的方法(至少在C#,Java中).
当然,如果我可以修改派生类,我可以使用复制粘贴(糟糕),宏(是的,我知道),mixins(不是这些语言)等.但这仍然是真正的丑陋.
这是具体的问题,但它发生在我身上好几次,我希望能够将静态成员"注入"派生类来优雅地解决问题.
非常感谢.
编辑:感谢很好的答案,在C++中,它可能也使用CRTP(奇怪的重复模板模式),但不是在C#/ Java(没有多重继承).当然,必须有权访问派生类并添加这个基类,所以问题仍然存在(如果没有其他方法,这看起来最好).
编辑2:使用当前语言看起来不可能.每个类的静态部分都不是继承(并且是正确的),但是没有与每个类关联的继承单例,因此这些问题不能如此优雅地解决.为了说明这一点,请看下面的代码:普通成员和静态成员是当前的OOP语言功能,"singleton"(或者任何单词)成员是我的建议/愿望:
class Base
{
static int sMemberBase;
int memberBase;
//my wish …Run Code Online (Sandbox Code Playgroud) 我需要一些复杂的数学库,所以我在使用不可变复杂的库和使用可变复杂的库之间犹豫不决.显然,我希望计算运行得相当快(除非它会杀死可读性等).
所以我创建了速度可变与不可变的简单测试:
final class MutableInt {
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public MutableInt() {
this(0);
}
public MutableInt(int value) {
this.value = value;
}
}
final class ImmutableInt {
private final int value;
public ImmutableInt(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public class TestImmutableSpeed {
static long testMutable(final int arrLen) {
MutableInt[] arrMutable = new MutableInt[arrLen];
for (int …Run Code Online (Sandbox Code Playgroud) 对于swing应用程序,组件的默认字体设置是当前主题,可以使用UIManager检索:
public class JavaTesting {
public static void main(String[] args) {
System.out.println(UIManager.get("Label.font"));
}
}
Run Code Online (Sandbox Code Playgroud)
这可以在JAVA_HOME/lib/swing.properties中针对应用程序范围进行调整,例如:
swing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel
Run Code Online (Sandbox Code Playgroud)
或者在命令行设置:
java -Dswing.defaultlaf=javax.swing.plaf.nimbus.NimbusLookAndFeel MyApp
Run Code Online (Sandbox Code Playgroud)
或者应用程序本身会记住它的外观和感觉,并将此值存储在配置(文件)中的某个位置.它可以工作,因为应用程序可以为自己设置外观,例如:
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
Run Code Online (Sandbox Code Playgroud)
这一切看起来都不错,但应用程序通常需要较小的字体(例如Label的不重要状态栏消息)或较大的字体(带有一些标题的Label).有没有推荐的方法呢? 作为高密度监视器的用户,我不得不丢弃许多java应用程序,使用这样的代码 - 从squirrel sql复制的源代码:
Font tmp = (Font)UIManager.get("Label.font");
if (tmp != null) {
Font font = tmp.deriveFont(10.0f);
_statusBarFontInfo = new FontInfo(font);
}
Run Code Online (Sandbox Code Playgroud)
此示例代码使状态栏完全不可读,但大多数组件都调整为新的,更大的字体.
为了创建我自己的应用程序,我可能会使用一些比例(例如主题字体的50%到150%),但硬编码0.50 - 1.50范围看起来也是一个糟糕的编码习惯.它并没有解决我没有源代码的应用程序的问题.这属于主题/ L&F(外观,外观和感觉).例:
FontUIResource Label_font_resource = (FontUIResource)javax.swing.UIManager.get("Label.font");
Font Label_font = Label_font_resource;
Font Label_font_bigger = Label_font.deriveFont(Label_font.getSize2D() * 1.5f);
Run Code Online (Sandbox Code Playgroud)
在我尝试一些丑陋的黑客之前,这是值得问的,比如自定义组件取代了swing默认值,或者Graphics2D.setFont调整,或任何其他可怕的东西.:-)
编辑:唯一存在的是尺寸变体,仅受Nimbus主题支持.允许的值为"迷你","小","常规","大".例:
JComponent mini …Run Code Online (Sandbox Code Playgroud) java ×3
c# ×1
c++ ×1
fonts ×1
immutability ×1
inheritance ×1
nimbus ×1
oop ×1
performance ×1
swing ×1
themes ×1