我知道在trait上使用类继承能够约束它可以混合的类。 这是一种众所周知的在mixin时添加限制的方法:
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
//your code
mViewPager = (ViewPager) findViewById(R.id.viewpager);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == R.id.tab_11) {
mViewPager.setCurrentItem(0);
} else if (menuItem.getItemId() == R.id.tab_22) {
mViewPager.setCurrentItem(1);
} else if (menuItem.getItemId() == R.id.tab_33) {
mViewPager.setCurrentItem(2);
}
mDrawerLayout.closeDrawers();
return true;
}
});
}
或
class Foo
trait FooTrait extends Foo
val pass = new Foo with FooTrait
class Bar
val error = new Bar with FooTrait //illegal inheritance: superclass Bar is not a subclass of the superclass Foo of the mixin trait FooTrait
这只是用于此目的的特殊语法吗?
我问这个是因为我无法弄清楚如何使用继承概念解释这个。 另外,如果你继承trait而不是抽象类,我无法解释相反的结果:
abstract class Foo
trait FooTrait extends Foo
class Bar
val error = new Bar with FooTrait //illegal inheritance
答案 0 :(得分:4)
这里要理解的关键事项如下:
traits
中混合而不是继承。混合与继承有重要区别。trait
的超类。如果您的trait
未声明超类,则其默认超类为AnyRef
。
现在,如果你做了类似以下的事情:
class Foo \\ 1
trait FooTrait extends Foo \\ 2
class Bar extends FooTrait \\ 3
第三行可以正确编译。但是当你做的时候
val bar = new Bar with FooTrait
无法编译。
原因是当您使用后一种形式时,您隐式创建了Bar
的子类。让我试着让它更清楚一些。当您说val bar = new Bar
bar
变量不是类Bar
的实例时。它是Bar
的匿名子类的实例。
所以,把所有这些放在一起,当你做val bar = new Bar with FooTrait
这样的事情时,你实际上要尝试的是创建一个包含两个超类的匿名类。
Bar
您通过Foo
Footrait
醇>
JVM不允许从多个类继承,无论它们是否是抽象的。从多个接口继承是很好的。这就是你最后一个例子的原因:
trait Foo
trait FooTrait extends Foo
class Bar
val pass = new Bar with FooTrait // no restriction!
编译很好,因为traits相当于Java中的接口。