如何在将属性传递给超类构造函数之前修改属性?

时间:2019-05-08 16:24:21

标签: java

一般问题:

给出一个这样的类:

public class Super {
    private String value;
    public Super(String initialValue)
    {
        this.value = initialValue;
    }
    public String getValue()
    {
        return value;
    }
}

以及类似的子类:

public class Sub extends Super {
    public Sub(String initialValue)
    {
        super(initialValue);
    }
}

在调用initialValue方法之前是否可以修改super()

这是我的特定用例:

我正在写一个小的包装ExoPlayer,就像这样:

public class BFPlayer extends PlayerView {
    private SimpleExoPlayer player;

    public BFPlayer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        TypedArray attributes = context.obtainStyledAttributes(attrs,
                R.styleable.BFPlayer);

        player = ExoPlayerFactory.newSimpleInstance(context);

        this.setPlayer(player);

        DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
                Util.getUserAgent(context, "TODO: USER AGENT STRING"));

        MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
                .createMediaSource(Uri.parse(attributes.getString(R.styleable.BFPlayer_videoSrc)));

        player.prepare(videoSource);

        player.setPlayWhenReady(true);
    }
}

ExoPlayer的PlayerView视图期望属性(在layout.xml文件中)使用蛇形大小写。例如:

  • use_artwork
  • default_artwork
  • hide_on_touch

然而,本机视图的 绝大多数 默认属性使用驼峰式大小写:

  • addStatesWithChildren
  • alwaysDrawnWithCache
  • animateLayoutChanges
  • animateCache
  • clipChildren
  • clipToPadding

因此,为了保持一致,我想用相同的驼峰案例属性替换ExoPlayer属性:

  • useArtwork
  • defaultArtwork
  • hideOnTouch

但是,因为super()必须在构造函数中的任何其他代码之前调用,所以我没有机会在超类初始化之前修改AttributeSet:

    public BFPlayer(Context context, AttributeSet attrs, int defStyle) {
        AttributeSet modifiedAttrs = camelToSnake(attrs);
        super(context, modifiedAttrs, defStyle);
        init(context, attrs, defStyle);
    }

这有招吗?还是根本不可能?

2 个答案:

答案 0 :(得分:4)

理想情况下,您将执行以下操作:

class Sub extends Super {
  private static String massageArgument(String incoming) { 
    return incoming.replaceAll("foo", "bar"); 
  }

  public Sub(String incoming) {
    super(massageArgument(incoming));
  }

并注意:该方法必须是静态的!您不能在Sub中对超级构造函数的调用中使用非静态方法。由于任何非静态方法都可能希望它对完全初始化的对象进行操作。您没有的东西,当您在调用 before 方法时,将调用“ this”和“ super”构造函数,并且可以完成它们的初始化工作!

另一种选择是使Sub构造函数成为 private ,并具有处理传入字符串的静态工厂方法,然后立即使用经过按摩的输入来调用new Sub()。 / p>

答案 1 :(得分:0)

package Sample;

public class Parent{

    public Parent() {
        System.out.println("Parent default constructor called");
    }

    public Parent(String value) {
        System.out.println("Parent patametrized (String) constructor called value :: "+value);
    }


    public static void main(String[] args) {
        Parent parent = new Child("Sample ");
    }
}

class Child extends Parent{

    public Child() {
        System.out.println("Child default constructor called");
    }

    public Child(String value) {
        super(value+" converted from child "); // either maipulate inside or call a static method
        System.out.println("Child parametrized (String) constructor called");
    }
}