2017-04-17 10 views
4

为什么GraphQL implements关键字需要重复的字段,是强制性的吗?就像文件中的例子:为什么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 
} 

如果是的话,是什么原因造成的?

堂妹如果我要重复,如果我改变的话,我需要改变无处不在......

回答

7

是的,这根据当前spec是强制性的:

对象类型必须包括相同名称的字段用于在接口中定义的每个字段。

它允许您更精确地指定派生类型中的字段类型。可以将字段更改为非空或接口或联合的某个特定子类型。以你为例,假设人类只与其他人类交朋友,而与机器人相同。那么下面的模式是有效的。

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

2

是的,它是强制性的。如果有帮助,可以将它看作类似于Java类和接口的类。接口有类型签名,但不能有实现。它在你写出所有实现的类中,并且类型签名被重复。这使您能够在类型签名中选择子类型或协变类型,因此它们可能不是,而是完全相同的

现在假设您正在使用来自graphql-js的JavaScript对象创建GraphQL架构。接口只是字段名称和类型。对象类型定义本身具有“实现”或resolveresolveType以及实际使其成为可执行模式的其他属性。

但是,您的示例使用模式语言,而不是“实现”。所以他们几乎是一个确切的重复彼此。你不一定需要每次都拼出来,你可以使用字符串插值来分享接口的一部分。

const characterFields = ` 
    id: String 
    name: String 
    friends: [Character] 
    appearsIn: [Episode] 
` 

const typeDefs = ` 
    interface Character { 
    ${characterFields} 
    } 

    type Human Implements Character { 
    ${characterFields} 
    homePlanet: String 
    } 
` 

编辑:类似于在Java比较,字段可能不准确相同的类型。正如RomanHotsiy指出的那样,您可以使类型不可为空或使用多态类型的子类型。

+0

非常感谢您的回答和比较的强大,但只有一个答案可以选择,组合将是最好的。 – lnshi

+0

@ andy-carlson 有一个外部文件包含'character'和'Human'的公共字段,然后添加到像'... characterFields'这样的字段之间有何区别? –