2 Вопрос: Как изменить атрибуты перед передачей их в конструктор суперкласса?

вопрос создан в Wed, May 8, 2019 12:00 AM

Общий вопрос:

Учитывая класс, подобный так:

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);
    }

Есть ли уловка с этим? Или это просто невозможно?

    
4
  1. Используйте статический метод для изменения аргументов
    2019-05-08 16: 26: 46Z
  2. Чтобы ответить на общий случай, вы можете использовать super(yourMethod(initialValie)), где yourMethod(..) вернет измененную версию initialValue.
    2019-05-08 16: 26: 50Z
2 ответа                              2                         

В идеале вы должны сделать что-то вроде:

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

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

И обратите внимание: этот метод должен быть статическим! Вы не можете использовать нестатический метод в этом вызове супер-конструктора в Sub. Как и любой нестатический метод, можно ожидать, что он работает с полностью инициализированными объектами. Этого у вас нет, когда вы вызываете метод перед , вызывается конструктор this и super, который может выполнять свою работу по инициализации!

Другой вариант - сделать конструктор Sub приватным и иметь статический метод фабрики, который манипулирует входящей строкой, а затем сразу же вызывает new Sub() с массированным вводом.

    
4
2019-05-08 17: 20: 51Z
  1. Он должен быть статичным. Вы не можете ссылаться на метод экземпляра при вызове конструктора через super.
    2019-05-08 16: 38: 43Z
  2. Я бы не подумал об использовании метода. Я столкнулся с проблемой необходимости изменить значение до вызова super() всего два часа назад. :)
    2019-05-08 16: 50: 50Z
  3. Вы упомянули, что метод должен быть статическим, но в своем примере вы не сделали метод статическим:)
    2019-05-08 17: 00: 23Z
  4. @ stevendesu большое наблюдение, большое спасибо!
    2019-05-08 19: 15: 08Z
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");
    }
}
    
0
2019-05-08 16: 45: 05Z
источник размещен Вот