Swing 通过扩展组件并使用SequentialContainer.Wrapper trait扩展Scala包装器类,我对traits有正确的理解吗?

Swing 通过扩展组件并使用SequentialContainer.Wrapper trait扩展Scala包装器类,我对traits有正确的理解吗?,swing,scala,inheritance,mixins,traits,Swing,Scala,Inheritance,Mixins,Traits,以下代码取自此帖子: 我一直在尝试制作定制包装,所以需要理解这一点,这很简单,但从那时起 我才刚刚开始熟悉Scala,所以我对它的特点有点不确定。所以我一直听到的是,特质就像多重遗传一样,你可以混合搭配它们 我画了一个图表,表示PopupMenu在整个继承结构中的位置。我只想澄清几件事: 1) 它似乎覆盖了组件中的lazy val peer:JComponent,还从SequentialContainer.Wrapper中获取contents属性?(紫色文本)是这样吗 2) 包装器还有一个抽象的

以下代码取自此帖子:

我一直在尝试制作定制包装,所以需要理解这一点,这很简单,但从那时起 我才刚刚开始熟悉Scala,所以我对它的特点有点不确定。所以我一直听到的是,特质就像多重遗传一样,你可以混合搭配它们

我画了一个图表,表示PopupMenu在整个继承结构中的位置。我只想澄清几件事:

1) 它似乎覆盖了组件中的lazy val peer:JComponent,还从SequentialContainer.Wrapper中获取contents属性?(紫色文本)是这样吗

2) 包装器还有一个抽象的def对等体:JComponent。。但这不是被覆盖的,所以这里根本不使用它

3) 令人困惑的是组件和Sequential.Wrapper有一些相同的属性:它们都有def publish和def subscribe(红色文本)。。但是弹出菜单将使用的是来自组件类的subscribe/publish

4) 为什么我们不能用组件来编写PopupMenu扩展SequentialContainer.Wrapper呢

希望不要一次问太多问题。非常感谢您的帮助,我是Scala的初学者。。

我将使用您的问题编号来回答:

  • 正确的

  • 对。最重要的特性是
    UIElement
    ,它定义了一个抽象成员
    def peer:java.awt.Component
    。然后您就有了
    Container
    ,它只添加了抽象成员
    def contents:Seq[Component]
    ,以便能够读取子组件
    Container.Wrapper
    Container
    的一个具体实现,它(抽象地)假设Java对等体是
    javax.swing.JComponent
    。请注意,在Java自己的层次结构中,
    javax.swing.JComponent
    Java.awt.Component
    的子类型,因此没有冲突。子类型可以细化其成员的类型(“协方差”)
    SequentialContainer
    通过说明
    内容
    是一个可变缓冲区(而不是只读序列)来细化
    容器
    。因此,它的实现
    SequentialContainer.Wrapper
    混合在
    Container.Wrapper
    中,但用标准的Scala缓冲区替换
    内容。在任何时候都没有给出一个具体的
    peer
    。为方便起见,
    组件确实实现了该成员,但是正如您所看到的,最后一个类
    弹出菜单
    覆盖了
    对等对象
    。由于类型系统的工作方式,所有参与的trait都可以访问
    peer
    ,但只有
    PopupMenu
    “知道”类型已被细化为
    javax.swing.jpopmenu
    。例如,
    SequentialContainer.Wrapper
    只知道存在一个
    javax.swing.JComponent
    ,因此它可以使用对等API的这一部分

  • Publisher
    特性是由
    UIElement
    引入的,因此您可以在从
    UIElement
    派生的所有类型中找到它在层次结构中多次出现相同的特征没有错。在最后一个类中,只有
    Publisher
    的一个实例,不存在它的多个“版本”。
    即使
    Publisher
    未在根目录下定义,但独立于例如
    组件
    SequentialContainer.Wrapper中,在最后一个类中只能得到一个实例

  • 这是一个简单的问题。在Scala中,您只能扩展一个类,但可以混合使用任意数量的特性<代码>组件是一个类,而其他所有东西都是特性。这是
    A类扩展为…


  • 总之,所有GUI元素都继承自trait
    UIElement
    ,它由
    java.awt.Component
    备份。具有子元素的元素使用trait
    Container
    ,所有允许您按特定顺序添加和删除元素的普通面板类型元素使用
    SequentialContainer
    。(并非所有面板都有顺序,例如
    BorderPanel
    没有顺序)。这些是抽象接口,要获得所有必要的实现,您需要
    .Wrapper
    类型。最后,为了获得一个可用的类,您有
    组件
    ,它扩展了
    UIElement
    ,并要求对等方是
    javax.swing.JComponent
    ,因此它可以实现所有标准功能

    实现新包装器时,通常使用
    组件
    并优化
    对等体
    类型,以便可以访问该对等体的特定功能(例如
    jpopmenu
    show
    方法)

    import scala.swing._
    import javax.swing.JPopupMenu
    
    class PopupMenu extends Component with SequentialContainer.Wrapper {
      override lazy val peer: JPopupMenu = new JPopupMenu with SuperMixin
    
      def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y)
    }