我如何在Java中使用接受扩展接口类型参数的函数来创建接口?
例如,使用接口ISelfComparable
如果A类对其进行了扩展,那么我希望它能够实现
bool compareTo(A other)
但是如果类B扩展了它,那么我希望它能够实现
bool compareTo(B other)
我知道我可以使用通用接口,但似乎不正确,因为A扩展ISelfComparable
没有任何意义。如果这不可能,那么在这种情况下的最佳实践是什么?
答案 0 :(得分:1)
通常的解决方案是自约束泛型,如Enum
类中所示。
interface Example<T extends Example<T>> {
void foo(T t);
}
public class ExampleImpl implements Example<ExampleImpl> {
@Override
public void foo(ExampleImpl example) {
}
}
它的工作原理有点令人头晕,但是例如here的解释很好。在here主题上也有很好的答案。
请注意,它并非万无一失,因为它允许这样做:
public class ExampleImpl2 extends Example<ExampleImpl {
@Override
public void foo(ExampleImpl example) {
}
}
但是在实践中,自我约束的习语用于表达您所追求的事物。
如果确实确实需要参数对象始终与this
完全相同,则必须进行运行时检查。 (这也引发了一个问题,为什么您需要它,但这会使我们脱离话题。)
答案 1 :(得分:0)
看看类java.lang.Comparable
:它有一个参数,该参数带有可以在compareTo
中使用的对象的类型。
比喻:
public interface ISelfComparable<T extends ISelfComparable<T>> {
boolean compareTo(T other);
}
答案 2 :(得分:0)
有一种方法可以检查参数的类型,但只能在运行时检查。例如,您可以在默认方法中实现类型检查:
List<Fragment>
然后,此接口的每个实现应如下所示:
instantiateItem(ViewGroup container, int position)
在这种情况下,如果您致电public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Attach the SectionsPagerAdapter to the ViewPager
SectionsPagerAdapter pagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.viewPager);
viewPager.setAdapter(pagerAdapter);
}
//
//
//Adapter class
private class SectionsPagerAdapter extends FragmentPagerAdapter {
private static final int PAGE_HOME = 0;
private int tabCount = 1;
private List<Fragment> fragmentList = new ArrayList<>();
private List<String> fragmentTitleList = new ArrayList<>();
//private FragmentManager fragmentManager;
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
//fragmentManager = fm;
//Default HomeFragment
HomeFragment homeFragment = new HomeFragment();
//Callback interface
homeFragment.setOnCategoryFragmentChangedListener(new HomeFragment.OnCategoryFragmentChangedListener() {
//This method will be called when a button in HomeFragment is clicked
@Override
public void onAddNewCategory(String categoryName) {
addNewCategory(categoryName);
}
});
fragmentList.add(homeFragment);
fragmentTitleList.add("Home");
}
@Override
public Fragment getItem(int position) {
return fragmentList.get(position);
}
@Override
public int getCount() {
return tabCount;
}
@Override
public CharSequence getPageTitle(int position) {
return fragmentTitleList.get(position);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
fragmentList.set(position, (Fragment) super.instantiateItem(container, position));
return fragmentList.get(position);
}
private void addNewCategory(String categoryName) {
CategoryFragment fragment = new CategoryFragment();
tabCount += 1;
fragmentList.add(fragment);
fragmentTitleList.add(categoryName);
notifyDataSetChanged();
}
}
}
,则会抛出interface ISelfComparable {
default boolean compareTo(ISelfComparable param) {
if (this.getClass() != param.getClass()) {
throw new IllegalArgumentException();
}
...
}
}