模式匹配通用返回类型

发布于 2024-12-29 16:29:38 字数 690 浏览 4 评论 0原文

编辑
把这个留给后人,但将近一年后,投票下来,很好……现在不会做像下面这样的事情,但在当时,开始使用 Scala,问题通常来自无知的地方……

原创
我知道我可以将模式匹配包装在指定泛型类型的方法中,如下所示:

def getTeam[T <: _Team](clazz: String): _Team =
  clazz match {
    case "roster" => new RosterController
    case "schedule" => new ScheduleController
  }

并获得一个有意义的类型(_Team)供编译器使用。

但是,我想知道是否可以在不使用包装方法且不使用 asInstanceOf[_Team] 样板的情况下执行此操作?也就是说,

clazz match {
  case "roster" => new RosterController.asInstanceOf[_Team]
  case "schedule" => new ScheduleController.asInstanceOf[_Team]
}

如果不可能的话,也不是世界末日,而是更愿意就地进行匹配,而不是分成一个单独的方法。

谢谢

EDIT
Leaving this for posterity, but nearly a year later, to get down voted, nice...would not do anything like the below now, but at the time, getting started with Scala, questions generally come from a place of ignorance....

ORIGINAL
I know I can just wrap a pattern match in a method with generic type specified like so:

def getTeam[T <: _Team](clazz: String): _Team =
  clazz match {
    case "roster" => new RosterController
    case "schedule" => new ScheduleController
  }

and get a meaningful type (_Team) for the compiler to work with.

However, I am wondering if it is possible to do this WITHOUT a wrapper method and without asInstanceOf[_Team] boilerplate? i.e. something other than

clazz match {
  case "roster" => new RosterController.asInstanceOf[_Team]
  case "schedule" => new ScheduleController.asInstanceOf[_Team]
}

Not the end of the world if not possible, but would prefer to do the matches in place vs. splitting into a separate method.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

得不到的就毁灭 2025-01-05 16:29:38

我不确定您认为这种方法发生了什么,但看起来您要么感到困惑,要么写下了错误的内容。

在您的示例中,T 是一个类型参数,上面由类型 _Team 界定(我假设它是一个类或一个特征)。您随后忽略了T,因此它可能是一个幻影类型,但从您的问题来看,但它看起来并不像这样。

不可能需要将RosterController 转换为_Team,因为它要么是一个,要么不是。我可以推断出这一点,因为 RosterController 在实例化它时必须是一个具体的类。它要么是 _Team 的子类型,要么不是。

如果 _Team 是一个特质,它可以混合在:

new RosterController with _Team

但因为你没有解释你实际上想要做什么,所以很难确定! RosterController 也参数化了吗?


编辑 - 从下面的评论中,您似乎想知道编译器将什么推断为表达式的结果类型,其中该表达式是 match 语句。

这是一个有用的示例,说明编译器如何推断出很多很酷的东西。

scala> class Bar; class Baz; trait Foo
defined class Bar
defined class Baz
defined trait Baz

现在让我们创建一个匹配表达式:

scala> def foo(s: String) = s match {
   | case "a" => new Baz with Foo
   | case _   => new Bar with Foo
   | }
foo: (s: String)ScalaObject with Foo

这样编译器就可以在这里正确推断出 Foo 。也许您可以重新表述您的问题,在 REPL 示例中提炼出您所期望的内容以及它与实际发生的情况有何不同。

I'm not sure what you think is going on in this method but it seems like you are either confused or have written the wrong thing down.

In your example, T is a type parameter, bounded above by the type _Team (which I assume is either a class or a trait). You subsequently ignore T, so it could be a phantom type but from your question, but it doesn't really seem like it.

You cannot possibly need to cast RosterController into a _Team because it either is one or it isn't. I can infer this because RosterController must be a concrete class as you are instantiating it. It's either a subtype of _Team or it is not.

If _Team is a trait, it can be mixed in:

new RosterController with _Team

But because you don't explain what you are trying to actually do, it's difficult to say for sure! Is RosterController also parameterized?


EDIT - from the comments below, it seems that you are wondering about what the compiler infers as the result type of an expression where that expression is a match statement.

Here's a useful example as to how the compiler can infer really quite a lot of cool stuff

scala> class Bar; class Baz; trait Foo
defined class Bar
defined class Baz
defined trait Baz

Now let's create a match expression:

scala> def foo(s: String) = s match {
   | case "a" => new Baz with Foo
   | case _   => new Bar with Foo
   | }
foo: (s: String)ScalaObject with Foo

So the compiler has correctly inferred Foo here. Perhaps you could rephrase your question, distilling in a REPL example exactly what you expect and how that differs from what actually happens.

枉心 2025-01-05 16:29:38

trait _Team{ def doWhat_TeamCanDo(s:String){println s} }

class MyTeamString(clazz: String)

 implicit def getTeam: _Team =
  clazz match {
    case "roster" => new RosterController with _Team
    case "schedule" => new ScheduleController with _Team
 }
}

implicit def strToMyTeamString(s:String):MyTeamString= MyTeamString(s)

现在,您可以在需要时将任何字符串隐式“转换”为 _Team:

"roster".doWhat_TeamCanDo("foo")

trait _Team{ def doWhat_TeamCanDo(s:String){println s} }

class MyTeamString(clazz: String)

 implicit def getTeam: _Team =
  clazz match {
    case "roster" => new RosterController with _Team
    case "schedule" => new ScheduleController with _Team
 }
}

implicit def strToMyTeamString(s:String):MyTeamString= MyTeamString(s)

now you can "convert" any string to a _Team when you need it, implicitly:

"roster".doWhat_TeamCanDo("foo")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文