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

逻辑案例类惯用的方法是什么

  •  3
  • igx  · 技术社区  · 6 年前

    FP的惯用方式是什么:假设我有这个

    trait Name
    
    object Name{
     def apply(name: String): Name = {
         if (name.trim.isEmpty || name.trim.length < 3)
           InvalidName
         else 
           ValidName(name.trim)
        }
     }
    
    case object InvalidName extends Name
    case class ValidName(name:String) extends AnyVal with Name
    

    现在我有了一些助手函数,比如

    def split = name.splitAt(" ")
    //some more functions 
    

    哪种方式更惯用:

    1. 把它们放在case类中,但这是如何使case类包含一些逻辑的,但是我可以这样做:

      val n = ValidName("john smith")

      val (first, last) = n.split

    2. 将它们放在专用对象中,然后方法将如下所示

      def split(n: ValidName) = n.name.splitAt(" ")

    3. 使用隐式类创建一个对象,该类将接受名称并调用方法

    你怎么认为?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Tim    6 年前

    在一个应用程序中添加逻辑并没有什么大问题 case class ,尤其是当它只是以不同的格式提取数据时。(将数据成员添加到 案例类 ).

    所以我会做选项1,不用担心!


    针对这些评论, 案例类 实际上,它只是创建一个包含大量有用的预实现方法的类的快捷方式。特别是 unapply 方法允许 案例类 用于模式匹配,以及 equals 对两个实例的字段进行元素级比较。

    还有很多其他方法可以从数据库中提取数据 案例类 以不同的方式。最明显的是 toString copy ,但也有其他类似的 hashCode 以及所有继承自 Product 例如 productIterator .

    自从 案例类 split 方法作为从数据库中提取数据的另一种方法 案例类 .

        2
  •  2
  •   Alvaro Carrasco    6 年前

    更惯用的说法是:

    case class Name private (name: String) {
      lazy val first :: last :: Nil = name.split(" ").toList
    }
    object Name {
      def fromString (name: String): Either[String, Name] = {
        if (name.trim.isEmpty || name.trim.length < 3) Left("Invalid name")
        else Right(new Name(name.trim))
      }
    }
    

    或者可能是这样:

    case class Name (first: String, last: String) {
      lazy val fullName = s"$first $last"
    }
    object Name {
      def fromString (name: String): Either[String, Name] = {
        if (name.trim.isEmpty || name.trim.length < 3) Left("Invalid name")
        else {
          val first :: last :: Nil = name.split(" ").toList
          Right(new Name(first, last))
        }
      }
    }
    

    在scala中,通过使用 Either 而不是通过继承。如果你有 N ,您不能对其调用任何函数,您可能必须对其进行模式匹配。但是像这样的类型 任何一个 已经有了如下功能 map , fold 等,这使得工作更容易。

    拥有私有构造函数有助于确保只能创建有效的 Name 因为只有通过 fromString 方法

    不要为此使用隐式。没有必要,只会让代码变得混乱。这不是它的真正用途。

        3
  •  0
  •   Jeremy    6 年前

    我认为这取决于上下文。在这种情况下,如果您使用的大多数方法只是对 String 方法,您可能需要考虑第四个选项:

    case class Name(name: String)
    implicit def NameToString(n: Name) = n.name
    
    Name("Iron Man").split(" ") // Array(Iron, Man)