2 Câu hỏi: Làm thế nào để sửa đổi các thuộc tính trước khi chuyển chúng đến một hàm tạo của lớp cha?

câu hỏi được tạo ra tại Wed, May 8, 2019 12:00 AM

Câu hỏi chung:

Đưa ra một lớp như vậy:

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

Và một lớp con như vậy:

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

Có cách nào để sửa đổi initialValue trước khi gọi phương thức super() không?

Đây là trường hợp sử dụng cụ thể của tôi:

Tôi đang viết một trình bao bọc nhỏ ExoPlayer, như vậy:

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's PlayerView Xem các thuộc tính mong đợi (trong tệp layout.xml) để sử dụng vỏ rắn. Ví dụ:

  • use_artwork
  • default_artwork
  • hide_on_touch
  • v.v

Tuy nhiên, đại đa số của các thuộc tính mặc định cho Chế độ xem gốc sử dụng trường hợp lạc đà:

  • addStatesWithChildren
  • alwaysDrawnWithCache
  • animateLayoutChanges
  • animateCache
  • clipChildren
  • clipToPadding
  • v.v

Do đó để thống nhất, tôi muốn thay thế các thuộc tính ExoPlayer bằng các thuộc tính trường hợp lạc đà giống hệt nhau:

  • useArtwork
  • defaultArtwork
  • hideOnTouch
  • v.v

Tuy nhiên vì phải gọi super() trước bất kỳ mã nào khác trong hàm tạo, tôi không có cơ hội sửa đổi Attribution Set trước khi siêu lớp khởi tạo:

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

Có một mẹo để làm điều này? Hay đơn giản là không thể?

    
4
  1. Sử dụng phương thức tĩnh để sửa đổi các đối số
    2019-05-08 16: 26: 46Z
  2. Để trả lời trường hợp chung, bạn có thể sử dụng super(yourMethod(initialValie)) trong đó yourMethod(..) sẽ trả về phiên bản sửa đổi của initialValue.
    2019-05-08 16: 26: 50Z
2 Câu trả lời                              2                         

Lý tưởng nhất là bạn sẽ làm một cái gì đó như:

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

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

Và lưu ý: phương pháp đó cần phải tĩnh! Bạn không thể sử dụng một phương thức không tĩnh trong cuộc gọi đó đến siêu cấu trúc trong Sub. Vì bất kỳ phương thức không tĩnh nào cũng có thể mong đợi rằng nó hoạt động trên các đối tượng được khởi tạo hoàn toàn . Mà bạn không có, khi bạn gọi phương thức trước thì hàm tạo "này" và "siêu" đã được gọi và có thể thực hiện công việc khởi tạo của chúng!

Tùy chọn khác sẽ là tạo nhà xây dựng phụ riêng tư và có một phương thức nhà máy tĩnh điều khiển chuỗi đến, sau đó gọi ngay new Sub() bằng đầu vào được tạo khối.

    
4
2019-05-08 17: 20: 51Z
  1. là tĩnh. Bạn không thể tham khảo một phương thức cá thể khi gọi hàm tạo thông qua siêu.
    2019-05-08 16: 38: 43Z
  2. Tôi sẽ không nghĩ đến việc sử dụng một phương thức. Tôi gặp phải vấn đề cần thay đổi giá trị trước khi gọi super() chỉ hai giờ trước. :)
    2019-05-08 16: 50: 50Z
  3. Bạn đã đề cập rằng phương thức này cần phải tĩnh, nhưng trong ví dụ của bạn, bạn đã không làm cho phương thức tĩnh :)
    2019-05-08 17: 00: 23Z
  4. @ stevendesu quan sát tuyệt vời, cảm ơn bạn rất nhiều!
    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
nguồn đặt đây