在typescript中创建一个生成器方法很简单:
class Foo {
*values() { yield 10 }
}
Run Code Online (Sandbox Code Playgroud)
但我想创建一个生成器属性,如下所示:
class Foo {
get *values() { yield 10 }
}
Run Code Online (Sandbox Code Playgroud)
但这似乎无效.我似乎无法找到任何对这个问题或变通方法的引用(除了明显使用Object.defineProperty明显,这会很糟糕,因为它将是无类型的).我错过了什么吗?这支持吗?如果没有,会是吗?
假设我有一个昂贵的函数doHardThings(),可以返回各种不同的类型,我想根据返回的类型采取行动.在Scala中,这是match构造的常见用法:
def hardThings() = doHardThings() match {
case a: OneResult => // Do stuff with a
case b: OtherResult => // Do stuff with b
}
Run Code Online (Sandbox Code Playgroud)
我正在努力弄清楚如何在Kotlin中干净利落地做到这一点而不引入一个临时变量doHardThings():
fun hardThings() = when(doHardThings()) {
is OneResult -> // Do stuff... with what?
is OtherResult -> // Etc...
}
Run Code Online (Sandbox Code Playgroud)
对于这个常见用例,什么是惯用的Kotlin模式?
我想使用 kotlin 数据类作为例外,这看起来不错:
data class MyException(val extraData: Any) : RuntimeException()
Run Code Online (Sandbox Code Playgroud)
我还希望能够cause在存在超类的情况下将 a 传递给超类。不幸的是,数据类只能在其主构造函数中包含val/ var,并且由于默认构造函数调用无参数RuntimeException()构造函数,因此似乎我根本无法在不总是需要cause传递并存储为类中的字段的情况下执行此操作,这我不想。
我想要的是这样的:
data class MyException(val extraData: Any) : RuntimeException() {
constructor(extraData: Any, cause: Throwable) : this(extraData) super(cause) {}
}
Run Code Online (Sandbox Code Playgroud)
看来,即使我不使用数据类,我仍然无法使用方便的var/val构造函数帮助器,因为它们只能位于主构造函数上,而主构造函数必须选择要使用的超级构造函数。我能想到的最好的就是这个,它非常冗长:
class MyException : RuntimeException {
val extraData: Any
constructor(extraData: Any) {
this.extraData = extraData
}
constructor(extraData: Any, cause: Throwable) : super(cause) {
this.extraData = extraData
}
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?是否真的没有办法根据重载构造函数有条件地调用不同的超类构造函数,并且仍然能够使用var/val参数语法?如果是这样,为什么?有更好的方法来做这种事情吗?
部分原因是我无法在 Kotlin 中创建没有参数的数据类,因此我object在这些情况下使用 s,例如
sealed class Node {
object Leaf : Node()
data class Branch(val left:Node, val right:Node) : Node()
}
Run Code Online (Sandbox Code Playgroud)
问题是,有时,我最终会得到该类的多个实例Leaf。显然,这种情况通常不会发生,但在使用某些框架和某些测试用例进行序列化和反序列化时会发生。
现在,您可能会说我应该修复这些情况,但很难知道它们可能在哪里,并且并不总是可能或不需要修改框架的反序列化语义。
因此,我希望s的所有object实例都充当相同的值,就像无参数data class(或 Scala 中的无参数case class)一样。
到目前为止,我最好的解决方案如下,包含在object我创建的每个可能遇到此问题的解决方案中:
object SaneLeaf {
override fun hashCode() = javaClass.hashCode()
override fun equals(other: Any?) = other?.javaClass == javaClass
}
Run Code Online (Sandbox Code Playgroud)
显然,这是冗长且容易出错的,因为似乎不可能将这些实现抽象到接口中。在对象不需要扩展另一个类的情况下,超类可以工作,但情况通常并非如此。
或者,我可以创建一个带有Nothing参数的数据类。但这似乎更像是一种黑客行为。
其他人如何处理这个问题?是否计划添加hashCode和equals实现遵循这些类的假定语义的对象(所有实例应该相等/相同的 hashCode)?
我在我的应用程序中使用groovy作为扩展语言.脚本扩展的类的构造函数接受变量参数.当我尝试实例化groovy类时,我从super()构造函数中的调用中获得了java.lang.ArrayIndexOutOfBoundsException .可以在独立的groovy脚本中轻松复制该问题:
// problem.groovy
class A {
A(float ... more) {}
}
class B extends A {
B() {
super();
}
}
new B();
Run Code Online (Sandbox Code Playgroud)
运行时,会产生:
$ groovy problem.groovy
Caught: java.lang.ArrayIndexOutOfBoundsException: 0
java.lang.ArrayIndexOutOfBoundsException: 0
at B.<init>(problem.groovy:7)
at problem.run(problem.groovy:11)
Run Code Online (Sandbox Code Playgroud)
第7行是super()课堂上的电话B.
这是语言本身的错误吗?我在网上找不到任何其他的提及.我是Groovy的新手,我可能不会理解这种语言的一些微妙之处.至少,这似乎应该在加载脚本时抛出编译器错误.
在对象文字中使用 getter 和 setter 时,我看不到在 Typescript 中访问外部“this”范围的简单方法。考虑以下:
class Report {
stuff: any[];
options = {
length: 10,
get maxLength() { return REPORT.stuff.length }
}
}
Run Code Online (Sandbox Code Playgroud)
whereREPORT想成为Report对象实例的引用。我意识到我可以通过在构造函数中设置选项并使用 avar REPORT = this或类似的来解决这个问题,但似乎不雅。有没有办法更干净地做到这一点?
我有一个接口(Java 中),它采用自引用泛型参数,我想在 Kotlin 中创建一个实现它的对象文字。在 Java 中,我通过不包含泛型类型(不安全)来做到这一点,但我不知道如何在 Kotlin 中做到这一点。
这是一个仅用 Kotlin 编写的示例,但在我的例子中,接口是用 Java 编写的。
interface Generic<V, T : Generic<V, T>> {
fun stuff(x: V)
}
class Test {
// In Java I would write new Generic() { ... }
val v = object : Generic<*, *> {
override fun stuff(x: Object) {
doSomethingThatDoesntCareAboutTypes()
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是这样的事情,但它不起作用:
val v = object<T : Generic<*, T>> : T {
override fun stuff(x: Object) {
doSomethingThatDoesntCareAboutTypes()
}
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做类似的事情而不需要更改接口,该接口位于不同的模块中并且不能轻易更改?
考虑以下<svg icon="close"></svg>为了显示图标而匹配的组件:
@Component({
selector: 'svg[icon]',
template: `<use [attr.xlink:href]="'icons.svg#'+icon"></use>`
})
export class SvgIconComponent {
@Input() icon: string;
}
Run Code Online (Sandbox Code Playgroud)
这会失败,因为 Angular 找不到该<use>元素,因为它不知道组件的内容在<svg>. 如果 Angular 会注意到selector确保了这个事实,那就太好了,但事实并非如此。
确切的错误是:
Uncaught Error: Template parse errors:
'use' is not a known element:
1. If 'use' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.
Run Code Online (Sandbox Code Playgroud)
显然我可以将 放在NO_ERRORS_SCHEMA组件的模块上,但我不想这样做,因为模块中还有其他组件,并且因为我希望未知元素错误检查起作用。
那么,我如何告诉 Angular 它应该将这个特定组件的内容视为 SVG …
我很难用英语描述,但问题是:
class Consumer<in T> {
fun consume(t: T) {}
}
class Accepter<in T>() {
// ERROR: Type parameter T is declared as 'in' but occurs in 'out' position in type Consumer<T>
fun acceptWith(value: T, consumer: Consumer<T>) {}
}
Run Code Online (Sandbox Code Playgroud)
可以这样修复:
fun <U : T> acceptWith(value: T, consumer: Consumer<U>) {}
Run Code Online (Sandbox Code Playgroud)
但我不明白这个问题。允许似乎并不不安全Consumer<T>。有人可以解释一下吗?
kotlin ×5
generics ×2
typescript ×2
angular ×1
data-class ×1
exception ×1
generator ×1
getter ×1
groovy ×1
polymorphism ×1
properties ×1
svg ×1