Java

时间:2018-08-02 23:34:43

标签: java android

我需要一种方法来接受两种类型并对它们执行相同的操作。

我知道我可以做到:

public void myMethod(TextView tv, ReadableMap styles) {
    if (styles.hasKey("fontFamily")) {
        String font = "fonts/" + styles.getString("fontFamily") + ".ttf";
        Typeface tf = Typeface.createFromAsset(context.getAssets(), font);
        tv.setTypeface(tf);
    }
    if (styles.hasKey("fontSize")) {
        tv.setTextSize(styles.getInt("fontSize"));
    }
    if (styles.hasKey("letterSpacing")) {
        tv.setLetterSpacing(PixelUtil.toPixelFromDIP(styles.getInt("letterSpacing")));
    }
}

public void myMethod(TextPaint tv, ReadableMap styles) {
    // copy paste the **exact** same code
}

TextViewTextPaint都有方法setTypeface(Typeface)setTextSize(float)setLetterSpacing(float),但是两个类除了{{1 }}。 (请注意,Object继承了TextPaint的方法。)这两个类都分别声明了这些方法,并具有相同的名称和签名。

因此,由于我无法相互转换,所以我想知道如何减少重复代码的数量?

4 个答案:

答案 0 :(得分:1)

创建一个共享通用方法签名setTypeFacesetTextSizesetLetterSpacing的接口类。 (基本上是适配器模式。)

public interface MyInterface {
   Typeface setTypeface(Typeface typeface);
   void setTextSize (float textSize);
   void setLetterSpacing(float letterSpacing);
}

将myMethod签名重新定义为

public void myMethod (MyInterface myi, ReadableMap styles) {
   //...change all your 'tv' references to myi
}

然后使用匿名类进行调用

// myTextView is in scope here...

myMethod(new MyInterface() {
      // partial implementation
      Typeface setTypeface(Typeface typeface) {
         myTextView.setTypeface(typeface);
      }, myStyles);
   }

// myTextPaint is in scope here   
myMethod(new MyInterface() {
      // partial implementation
      Typeface setTypeface(Typeface typeface) {
         myTextPaint.setTypeface(typeface);
      }, myStyles);
}

或创建同时为TextView和TextPaint实现MyInterface的包装器类。

答案 1 :(得分:0)

我对我的评论表示歉意,我应该检查超类,并应该使用使我的观点清晰可见的词而不是断言。为了解决这个问题,我尝试了以下方法,并且确实有效。由于目前没有可用的Android SDK,因此我创建了自己的TextView和TextPaint类,并使用 reflection 调用方法,因为我们已经知道它们的签名。

首先,将您的方法签名更改为public void myMethod(Object tv, ReadableMap styles)

这显示了如何调用setTextSize方法,但是所有其他方法的概念也应相同。

    tv.getClass()
            .getMethod("setTextSize", float.class)
            .invoke(tv, styles.getInt("fontSize"));

您可以了解有关invoking methods via their names using Java Reflection的更多信息。

答案 2 :(得分:0)

怎么样

 public void myMethod(TextView tv, String styles, TextPaint tp) {
    //must tv == null -> tp != null or tv != null -> tp == null
    if(tv != null){
        tp = tv.getPaint();
    }

   //doSomthing
}

答案 3 :(得分:-2)

这很容易解决,但是您需要了解多态性的基本概念。
为了做到这一点,您需要在这两种类型之间有一个共同的祖先。

public void myMethod(TextView tv, ReadableMap styles) {this.method(tv,styles);}

public void myMethod(TextPaint tv, ReadableMap styles) {this.method(tv,styles);}

private void method(CommonAncestor tv, ReadableMap styles){/*do your stuff*/}

您的两个班级ClassInterface的共同祖先是extendsimplements

此祖先必须同时提供您要调用的常用方法

  • 如果要在项目中创建这些类,则可以简单地创建祖先并将其扩展

  • 如果它们是内置类型,则可以检查它们的树线并查找是否两个类共享一个具有相同名称和逻辑的方法,通常它们共享一个祖先变量

  • 如果没有这样的祖先,并且您想要创建这种“无重复”方法,则必须使用反射...但是,这完全是一个坏主意,某种代码气味等待崩溃,我拒绝自己教它