代码之家  ›  专栏  ›  技术社区  ›  Suma

将参数列表转发到函数

  •  0
  • Suma  · 技术社区  · 11 年前

    我有一个类实现了一些功能(为L系统提供了一个海龟图形界面,但这在这里并不重要):

    abstract class LSystem
    {
      def BranchBegin()
      def BranchEnd()
      def Rotate(axis:Vector3f, angle:Float)
      def MoveForward(dist:Float)
      def DrawForward(size:Float, color:ColorRGBA)
      def DrawSphere(size:Float, color:ColorRGBA)
    }
    

    我有一种特质激励一些助手:

    trait LSystemShortcuts {
      def < ()(implicit lsys:LSystem)= lsys.BranchBegin()
      def S(size:Float, color:ColorRGBA)(implicit lsys:LSystem)= lsys.DrawSphere(size,color)
      def > ()(implicit lsys:LSystem)= lsys.BranchEnd()
    }
    

    最后是一个单独的L系统,看起来像这样:

    class RoundTree(implicit lsys:LSystem) extends LSystemShortcuts {
      // TODO: move to LSystemShortcuts 
      def F = lsys.DrawForward _
      def R = lsys.Rotate _
      def M = lsys.MoveForward _
    
      val degree = PI.toFloat/180
      val colorCrown = ColorRGBA.SRGB(0.1f,0.4f,0.05f, 1)
      val colorTrunk = ColorRGBA.SRGB(0.1f,0.1f,0.05f,1)
    
      def C(size:Float, iterations:Int) = {
        if (iterations>0) {
    
          F(size*0.5f,colorTrunk)
    
          <
          C(size*0.5f,iterations-1)
          >
    
          <
          R(Vector3f(0,0,1),+75*degree)
          C(size*0.3f,iterations-1)
          >
    
          // some more rendering code here
    
        }
        else
        {
          F(size,colorTrunk)
          M(size*0.6f)
          S(size*0.7f,colorCrown)
        }
      }
    }
    

    请注意,当前快捷方式 F , R M 直接在 RoundTree 班我想把它搬到 LSystemShortcuts 但我希望避免重复参数列表(这是通过使用部分应用的函数来完成的),就像对S快捷方式所做的那样。它很容易使用 LSystem快捷方式 作为一个基类,但我不喜欢这样的设计,特质似乎更合适。

    在定义函数时,是否有某种方法可以转发参数列表?大致如下:

    def R(_)(implicit lsys:LSystem) = lsys.Rotate _
    

    或者其他设计 LSystem快捷方式 作为一个成员而不是一种特质,这会让我实现这一点?

    2 回复  |  直到 11 年前
        1
  •  1
  •   tgr    11 年前

    嗯,我能猜出一种肮脏的变通方法。你可以改变你的定义 trait 具有受保护的成员。

    trait A {
      protected var i: Int = 0  // has to be initialized, won't compile otherwise
      def print = println(i)
    }
    

    之后,您可以按如下方式使用该成员:

    class B extends A {
      i = 10
      print
    }
    

    的呼叫 new B() 将打印 10 到控制台。
    我希望这能像预期的那样回答你的问题。否则,我会很乐意尝试找出另一个解决方案。

        2
  •  0
  •   Gabriele Petronella    11 年前

    据我所知,这是不可能的,因为scala不支持 point-free style notation 正如Haskell所做的。

    恐怕除了明确地传递参数之外,没有其他方法。

    推荐文章