【问题标题】:Java inheritance: "Casting" variable in abstract class as staticJava继承:抽象类中的“铸造”变量为静态
【发布时间】:2012-08-03 11:31:08
【问题描述】:

我正在寻求减少我的 Android 项目中的冗余代码。让我告诉你我已经拥有的东西。

我有两个主要的观点。一个称为 MapView,它是一个包含可以缩放、平移等位图的 View。另一个称为 StepInfoView,它是一个包含静态数据的 View,例如坐标数组和有关这些坐标的信息。此视图也以与 MapView 相同的方式进行缩放和平移,但是,缩放因子和平移量需要独立于 MapView。

StepInfoView 扩展了几个不同的类(总共 6 个),所有这些都需要同步(坐标绘制在一个上,坐标之间的线绘制在另一个上,等等)。

所以,这里是我的代码的要点,目前:

public class MapView extends View
{
    protected float scale = 1;

    protected class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        @Override
        public boolean onScale(ScaleGestureDetector detector)
        {
            scale *= detector.getScaleFactor());
            return true;
        }

    }

    }
... 

public class StepInfoView extends View
{
    static protected float scale = 1;
    protected class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        @Override
        public boolean onScale(ScaleGestureDetector detector)
        {
            scale *= detector.getScaleFactor());
            return true;
        }

    }
}
...
public class StepView extends StepInfoView
{  
    // Custom onDraw, same scale as PathView
}
public class PathView extends StepInfoView
{
    // Custom onDraw, same scale as StepView
}

如您所见,onScale 是相同的。我想创建一个抽象类来保存缩放功能,我们称之为 RootView。 MapView 和 StepInfoView 都有比例尺,但我不能在 RootView 中使比例尺为静态,因为 MapView 比例尺必须独立于 StepInfoView。这是我知道可行的解决方案,但我不喜欢 getter 和 setter 的混乱:

abstract class RootView extends View
{
    abstract protected float getScale();

    abstract protected void setScale(float s);
    protected class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
    {
        @Override
        public boolean onScale(ScaleGestureDetector detector)
        {
         setScale(getScale() * detector.getScaleFactor());
         return true;
        }
    }
}
...
public class MapView extends RootView
{
    public float scale = 1;
    protected float getScale(){
        return scale;
    }

    protected void setScale(float s){
        scale = s;
    }
}

public class StepInfoView extends RootView
{
    public static float scale = 1;
    protected float getScale(){
        return scale;
    }

    protected void setScale(float s){
        scale = s;
    }
}
public class StepView extends StepInfoView
{  
    // Custom onDraw, same scale as PathView
}
public class PathView extends StepInfoView
{
    // Custom onDraw, same scale as StepView
}

这正是我希望它工作的方式,但是再一次,有重复的相同代码(getter 和 setter 以及 MapView 和 StepInfoView 中的“比例”变量)。

我希望我能在 RootView 中声明一个非静态比例并在 StepInfoView 中将其“转换”为静态。这不太可能......

你能帮帮我吗?

【问题讨论】:

    标签: java inheritance static abstract


    【解决方案1】:

    一个浮点数大约需要 4 个字节。拥有另一个类将使用比这更多的内存。由于对象通常是 8 字节对齐的,因此它甚至可能不会使对象更小。

    如果您想避免复杂性,我会将字段保留为非静态。

    你可以有

    class RootView {
        protected final float[] scale;
    
        RootView() {
            scale = new float[] { 1.0f };
        }
    
        protected RootView(float[] scale) {
            this.scale = scale;
        }
    
        public boolean onScale(ScaleGestureDetector detector) {
            scale[0] *= detector.getScaleFactor();
            return true;
        }
    }
    
    class StepInfoView extends RootView {
        static final float[] scale = { 1.0f };
    
        StepInfoView() {
            super(scale);
        }
    

    【讨论】:

    • 我不关心这个应用程序的内存。将该字段保留为非静态需要我更新所有扩展 StepBaseInfo 的类,如果比例发生变化。
    • 因此,这仅适用于缩放,但我还有一个变量“位置”,即 MapView 和 StepInfoViews 的平移量,其处理方式与缩放相同(对于地图,StepInfo 的静态)。我可以在 MapView 和 StepInfoView 中都做 super.pan(x,y) 吗?
    • 你可以这样使用new Point(x, y)
    • 我真的不想只在构造函数中完成所有工作。我希望能够更新比例而无需创建新的 StepInfoViews。
    • 我慢慢开始看到丑陋的现实。
    【解决方案2】:

    将 scale 字段移动到 listener,并提供 get 和 set。

    在视图中,保存对侦听器的引用,以便您可以访问比例。

    对于 MapView,为每个视图实例注册不同的侦听器,以便它们具有不同的比例。

    对于 StepInfoView,为每个视图实例注册相同的侦听器,使它们具有相同的比例。您可以将侦听器的引用存储在静态字段中。

    【讨论】:

    • 如果你有两个对象通信,你需要方法让他们通信。由于您只有一个值可以从侦听器与视图进行通信,因此您要么在两者之间共享一个字段(如您所见,这很脆弱并导致重复),要么您拥有一个将值推送到视图的函数( setter)或从侦听器中提取值的函数(getter,或公共字段)。从同一个监听器拉出多个视图比让一个监听器推送到多个视图更简单。
    【解决方案3】:

    为什么不将scale 字段移到RootView 类中?

    更新:刚刚收到。我认为有一个聚合的地方:为 stepinfo scale 值创建一些对象容器,并通过 StepInfoView 传递。

    无论如何,我认为最简单的方法是使用 getter。

    【讨论】:

    • 我需要缩放在 StepInfoView 中是静态的。如果我在 RootView 中将其设为静态,则 StepInfoViews 和 MapViews 将不会相互独立缩放。
    • "为 stepinfo 比例值制作一些对象容器,并通过 StepInfoView 的"对不起,但我不明白你的建议。
    猜你喜欢
    • 2011-08-05
    • 2015-04-07
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 2019-10-17
    • 2011-04-02
    相关资源
    最近更新 更多