Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
正确使用scala特性和类型_Scala - Fatal编程技术网

正确使用scala特性和类型

正确使用scala特性和类型,scala,Scala,scala新手,试图掌握类系统的窍门。下面是一个简单的设置: sealed trait Shape{ def sides:Int } final case class Square() extends Shape { def sides() = 4 } final case class Triangle() extends Shape { def sides() = 3 } 现在,我想创建一个函数,它接受任何类型的shape,我们知道它将实现sides()方法,并使用该方法 d

scala新手,试图掌握类系统的窍门。下面是一个简单的设置:

sealed trait Shape{
  def sides:Int
}

final case class Square() extends Shape {
  def sides() = 4
}

final case class Triangle() extends Shape {
  def sides() = 3
}
现在,我想创建一个函数,它接受任何类型的
shape
,我们知道它将实现
sides()
方法,并使用该方法

def someFunction(a: Shape)={
    val aShape = a()
    aShape.sides()
}
但是这在
val aShape=a()
处遇到了一个错误,因为没有类型
a


我意识到在这个例子中,创建
someFunction
是过分的,因为
sides()
可以直接从对象访问。但是我的主要问题是在
someFunction
的上下文中-我想将一个类传递给一个函数,并实例化该类的一个对象,然后对该对象执行一些操作。谢谢您的帮助。

除非
shape
具有
apply
功能,否则您不能对
shape
对象调用
()

如果要将
aShape
分配给
a
,只需编写
val aShape=a

但由于我没有看到附加值,您不妨直接在
a
上调用
sides
函数:

def someFunction(a:shape) = {
  val sides = a.sides
  // use sides
}

你想用那行代码做什么?您已经有了一个
形状
,传入的形状名为
a
。只需删除该行并调用
a.sides()


在风格上,有几个问题。首先,类名应该以大写字母开头。其次,
sides
似乎是一个不可变的属性,而不是一个变异的方法,因此应该声明并重写它,而不使用括号。您还需要在子类中使用
override
修饰符。最后,您可以不使用空括号:
{4}
应该是
4

这是您所写内容的最接近的翻译:

sealed trait Shape {
  def sides: Int
}

case object Square extends Shape {
  override val sides = 4
}

case object Triangle extends Shape {
  override val sides = 3
}

def someFunction(a: Shape) =
  val shapeSides = a.sides
一些注意事项:

  • scala中的类应该是CamelCase
  • 子类没有实例成员,因此可以使用单例对象
  • 如果您有
    a:Shape
    ,则表示
    a
    Shape
    ,并且您还没有定义任何可以调用
    ()
    的内容
  • 当内部只有一个表达式时,可以省略大括号
  • 如果是静态的,可以使用
    val
    覆盖
    def

    • 有几种方法可以做到这一点。一个是复杂的,第二个稍微简单一点,第三个是最简单的。 只需将
      someFunction
      的定义更改为

      def someFunction(a: ()=>Shape)={
        val aShape = a()
        aShape.sides
      }
      
      所以
      someFunction(Square)
      return
      4
      someFunction(Triangle)
      返回3。请注意,这只适用于
      case类
      es,因为我们在这里传递的实际内容不是类本身,而是自动生成的

      但更常见的情况是,不需要定义类,您可以在任何上下文中编写,顶层除外,就像

      def square() = new Shape{
        def sides() = 4
      }
      
      def triangle() = new Shape{
        def sides() = 3
      }
      
      下一件事:参数列表为空的方法通常作为有副作用的方法读取。因此,像这样定义类型更方便

      sealed trait Shape{
        def sides:Int
      }
      
      如果你像这样定义你的建设者

      def square = new Shape{
        def sides = 4
      }
      
      def triangle = new Shape{
        def sides = 3
      }
      
      您应该将它们用作
      someFunction(square)
      告诉您将使用方法调用,而不是它返回的值


      最后一件事是:如果你真的需要代码,它会创建一些对象,但它可能包含复杂的计算、资源处理或一些可能的异常,所以你想保持它的执行直到它真的需要,你可以使用相当于R的代码,我想你熟悉它,它是一个值,不是函数、方法、构造函数……感谢您的帮助。我意识到在这个例子中,创建
      someFunction
      是过分的,因为
      sides()
      可以直接从对象访问。但是我的主要问题是在
      someFunction
      的上下文中-我想向该函数传递一个类,并实例化该类的一个对象,然后对该对象执行一些操作。我会澄清这个问题。你通常不会先传入一个类,然后创建一个实例,而是传入一个实例。是否要根据输入的边数创建实例?你想解决的真正问题是什么?谢谢,我一直在想这个错误,这有助于澄清我的理解。我将尝试提出一个我实际问题的简洁版本。