继承能够限制mixin组成目标的原因

时间:2015-09-12 13:44:56

标签: scala inheritance mixins traits

我知道在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

1 个答案:

答案 0 :(得分:4)

这里要理解的关键事项如下:

  1. 在Scala traits中混合而不是继承。混合与继承有重要区别。
  2. 当你混入一个特征时,你会隐含地继承trait的超类。
  3. 如果您的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这样的事情时,你实际上要尝试的是创建一个包含两个超类的匿名类。

    这两个超类
      您明确继承自的
    1. Bar 您通过Foo
    2. 继承的
    3. Footrait

      JVM不允许从多个类继承,无论它们是否是抽象的。从多个接口继承是很好的。这就是你最后一个例子的原因:

      trait Foo
      trait FooTrait extends Foo
      class Bar
      val pass = new Bar with FooTrait // no restriction!  
      

      编译很好,因为traits相当于Java中的接口。