为什么 GraphQL `implements` 需要复制字段,这是强制性的吗?如果有,背后的原因是什么?
Why GraphQL `implements` need to duplicate the fields, is that mandatory? If yes, what is the underlying reasons?
为什么 GraphQL implements
关键字需要复制字段,这是强制性的吗?喜欢文档中的例子:
enum Episode { NEWHOPE, EMPIRE, JEDI }
interface Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
如果是,背后的原因是什么?
因为如果我必须复制,如果我改变了那么我需要改变所有地方...
是的,这是强制性的。如果有帮助,请将其视为类似于 Java 类 和接口。接口具有类型签名,但不能具有实现。在 类 中,您写出了所有的实现,并且类型签名会重复。这使您能够在类型签名中选择子类型或协变类型,因此它们可能完全相同。
现在假设您正在使用 graphql-js 中的 JavaScript 对象创建 GraphQL 模式。接口只是字段名称和类型。对象类型定义本身具有 "implementation," 或 resolve
、resolveType
和其他实际使其成为可执行模式的属性。
然而,您的示例使用模式语言,它根本没有 "implementation"。所以它们几乎是彼此的精确重复。不一定每次都拼出来,可以用字符串插值来共享部分界面。
const characterFields = `
id: String
name: String
friends: [Character]
appearsIn: [Episode]
`
const typeDefs = `
interface Character {
${characterFields}
}
type Human Implements Character {
${characterFields}
homePlanet: String
}
`
编辑:类似于Java比较,字段可能不完全相同类型。正如 RomanHotsiy 指出的那样,您可以使类型不可为空或使用多态类型的子类型。
是的,根据当前spec:
这是强制性的
The object type must include a field of the same name for every field defined in an interface.
它允许您在派生类型中更精确地指定字段类型。字段可以更改为非空或某个接口或联合的特定子类型。以你的例子为例,让我们假设人类只与其他人成为朋友,机器人也是如此。那么下面的schema是有效的。
interface Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String
name: String
friends: [Human] # <- notice Human here
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String
name: String
friends: [Droid!]! # <- specified Droid here + added not null
appearsIn: [Episode]
primaryFunction: String
}
对象字段可能包含未在接口字段中定义的附加参数(但不得要求任何附加参数)。
查看规范了解更多详情:Object type validation
为什么 GraphQL implements
关键字需要复制字段,这是强制性的吗?喜欢文档中的例子:
enum Episode { NEWHOPE, EMPIRE, JEDI }
interface Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
primaryFunction: String
}
如果是,背后的原因是什么?
因为如果我必须复制,如果我改变了那么我需要改变所有地方...
是的,这是强制性的。如果有帮助,请将其视为类似于 Java 类 和接口。接口具有类型签名,但不能具有实现。在 类 中,您写出了所有的实现,并且类型签名会重复。这使您能够在类型签名中选择子类型或协变类型,因此它们可能完全相同。
现在假设您正在使用 graphql-js 中的 JavaScript 对象创建 GraphQL 模式。接口只是字段名称和类型。对象类型定义本身具有 "implementation," 或 resolve
、resolveType
和其他实际使其成为可执行模式的属性。
然而,您的示例使用模式语言,它根本没有 "implementation"。所以它们几乎是彼此的精确重复。不一定每次都拼出来,可以用字符串插值来共享部分界面。
const characterFields = `
id: String
name: String
friends: [Character]
appearsIn: [Episode]
`
const typeDefs = `
interface Character {
${characterFields}
}
type Human Implements Character {
${characterFields}
homePlanet: String
}
`
编辑:类似于Java比较,字段可能不完全相同类型。正如 RomanHotsiy 指出的那样,您可以使类型不可为空或使用多态类型的子类型。
是的,根据当前spec:
这是强制性的The object type must include a field of the same name for every field defined in an interface.
它允许您在派生类型中更精确地指定字段类型。字段可以更改为非空或某个接口或联合的特定子类型。以你的例子为例,让我们假设人类只与其他人成为朋友,机器人也是如此。那么下面的schema是有效的。
interface Character {
id: String
name: String
friends: [Character]
appearsIn: [Episode]
}
type Human implements Character {
id: String
name: String
friends: [Human] # <- notice Human here
appearsIn: [Episode]
homePlanet: String
}
type Droid implements Character {
id: String
name: String
friends: [Droid!]! # <- specified Droid here + added not null
appearsIn: [Episode]
primaryFunction: String
}
对象字段可能包含未在接口字段中定义的附加参数(但不得要求任何附加参数)。
查看规范了解更多详情:Object type validation