如何从Scala中的扩展类中获取值?

如何从Scala中的扩展类中获取值?,scala,Scala,我正在创建一个命令行应用程序,它读取用户输入的内容,然后用我刚刚启动的数据发出POST请求 我的问题是,我从来没有见过一个类像这样扩展,这让我很反感。如何从CommandApp获取值,以便在主对象中使用它 import cats.implicits._ import com.monovore.decline._ object Main extends CommandApp(name = "hello-world", header = "Says hello!

我正在创建一个命令行应用程序,它读取用户输入的内容,然后用我刚刚启动的数据发出POST请求

我的问题是,我从来没有见过一个类像这样扩展,这让我很反感。如何从CommandApp获取值,以便在主对象中使用它

import cats.implicits._
import com.monovore.decline._


object Main extends CommandApp(name = "hello-world",
  header = "Says hello!",
  main = {
    val userOpt = Opts.option[String]("target", help = "Person to greet.").withDefault("world")

    val quietOpt = Opts.flag("quiet", help = "Whether to be quiet.").orFalse

    (userOpt, quietOpt).mapN { (user, quiet) =>
      if (quiet) println("...")
      else println(s"Hello $user!")
    }
  }) {


  // How do I get the value from user into here.
  // Eventually I will want to use that user data variable for a POST request.


}

如果我理解正确,您希望模式匹配主对象中CommandApp的case类参数吗

import cats.implicits._
import com.monovore.decline._


object Main extends CommandApp(name = "hello-world",
  header = "Says hello!",
  main = {
    val userOpt = Opts.option[String]("target", help = "Person to greet.").withDefault("world")

    val quietOpt = Opts.flag("quiet", help = "Whether to be quiet.").orFalse

    (userOpt, quietOpt).mapN { (user, quiet) =>
      if (quiet) println("...")
      else println(s"Hello $user!")
    }
  }) {


  // How do I get the value from user into here.
  // Eventually I will want to use that user data variable for a POST request.


}
在Scala中,这是不可能的,因为Main是CommandApp的子类,而不是相反,您只能将模式匹配到子case类。但你可以使用特质:

声明一个没有直接功能的新特性 CommandApp必须继承这种特性 将主对象转换为该特征类型 模式匹配 因为我没有你的类定义,所以我写了一个小例子。假设你的班级看起来像这样:

case class Test(str:String)
class MainTest extends Test("Hello World!")
val t = new MainTest()
t match{
     case Test(str) => println(str)
     case _ => println("Could not match")
}
object Main{
    case class Test(str:String)
    class MainTest extends Test("Hello World!")

    def main(args:Array[String]){
        val t = new MainTest()
        t.asInstanceOf[Any] match{
            case Test(str) => println(str)
            case _ => println("Could not match")
        }
    }
}
您希望访问Test的str值,如下所示:

case class Test(str:String)
class MainTest extends Test("Hello World!")
val t = new MainTest()
t match{
     case Test(str) => println(str)
     case _ => println("Could not match")
}
object Main{
    case class Test(str:String)
    class MainTest extends Test("Hello World!")

    def main(args:Array[String]){
        val t = new MainTest()
        t.asInstanceOf[Any] match{
            case Test(str) => println(str)
            case _ => println("Could not match")
        }
    }
}
这将不起作用,因为MainTest不是案例类,因此无法进行模式匹配。但如果您声明了测试继承的新特性:

trait InheritanceTrait
case class Test(str:String) extends InheritanceTrait
class MainTest extends Test("Hello World!")
您可以通过将MainTest对象强制转换为InheritanceTrait来进行模式匹配,InheritanceTrait具有模式匹配子类,因此可以进行模式匹配:

val t = new MainTest()
t.asInstanceOf[InheritanceTrait] match{
    case Test(str) => println(str)
    case _ => println("Could not match")
} //prints "Hello World!"
如果您不想或根本无法声明CommandApp的超类,您可以通过将t转换为Any类型来使用肮脏的替代方法,因为每个类都继承自Any。这样也行

我的例子如下:

case class Test(str:String)
class MainTest extends Test("Hello World!")
val t = new MainTest()
t match{
     case Test(str) => println(str)
     case _ => println("Could not match")
}
object Main{
    case class Test(str:String)
    class MainTest extends Test("Hello World!")

    def main(args:Array[String]){
        val t = new MainTest()
        t.asInstanceOf[Any] match{
            case Test(str) => println(str)
            case _ => println("Could not match")
        }
    }
}
我希望这解决了你的问题

应该注意的是,CommandApp不是一个case类,它是一个常规的抽象类

CommandApp的预期用途似乎是,您的整个程序进入main,当main完成时,您的程序完成。这个类的名称以App c.f.IOApp结尾,并具有main属性,这就证明了这一点

所以你要做的是在其他地方定义一个函数,它接受你已经验证过的,你想使用的任何值,例如user,在这个例子中,作为参数,并对它们进行处理,例如

// Disclaimer: I'm guessing from the code that userOpt is Option[String]
def sendUserAsPostRequest(user: String): Unit = {
  // sending the user as a POST is left as an exercise for the reader
}
只要Main构造了该类的实例,就可以将该函数放置在Main中、不同的对象中或不同的类中。你是主要的,然后看起来就像我假设,对于这个,你对安静不感兴趣:


我刚开始学习这个图书馆。我正在尝试获取user的值。你没有mapN中的值吗?谢谢你的详细回答,它真的很有用。如果我把printlnuser改成user,看看我在哪里打印。如何将该用户值放入主类?除非您使用一个附加属性修改CommandApp,您可以在其中存储该值,否则这是不可能的,因为该用户值位于lambda内部,因此是一个局部变量,基本模式匹配无法访问该局部变量。当然,静态存储这个变量是可能的,但这不是一个好的解决方案