在 GraphQL 中,接口(InterfaceTypeDefinition)也是一種命名字段集合,定義規則與對象類型極其類似,一樣支持 字段名、類型、參數 三要素。 與 OOP 概念相似,GraphQL 中的接口只是對資源的抽象描述,必須被其餘對象類型實現,才能正常使用。咱們來看個例子:git
interface NamedEntity {
name: String
}
type User implements NamedEntity {
id: ID!
name: String
}
複製代碼
上例中,NamedEntity
即爲接口;User
是實現了該接口的對象類型。注意,實現類必須實現接口的全部字段,字段名、類型、參數都必須與接口匹配。 GraphQL 支持多繼承:github
interface NamedEntity {
name: String
}
interface Node {
id: ID!
}
'''
非法示例:
沒有實現Node接口的id字段
'''
type User implements NamedEntity & Node {
name: String
}
複製代碼
那麼,在什麼場景下應該使用接口?咱們要理解,接口是對資源的抽象描述,不必定完備、詳盡,但每每能表述多類類似資源的共同特徵,因此若是服務中存在一些具有共性的類型,而用戶須要關注共同的這一部分,就應該使用接口。 好比,咱們有三種類型的商品:飲料、圖書、電器:bash
type Drinks {
id: ID!
name: String!
price: Float!
'''
容量,單位爲ml
'''
capacity: Float!
}
type Book {
id: ID!
name: String!
price: Float!
'''
做者
'''
author: [People]
issn: String!
}
type ElectricalEquipment {
id: ID!
name: String!
price: Float!
'''
生產商
'''
manufacturer: Company
}
複製代碼
上面三個商品對象有三個類似的屬性:id
、name
、price
,是商品資源的不一樣類型。如今,咱們須要實現根據名稱搜索商品,若是接口功能,就必須使用近似的邏輯,在三種類型節點上,重複定義三次;若是將來咱們增長更多公共查詢邏輯,咱們又得把邏輯重複三遍,這顯然不是一個好的設計。這種狀況下就適合使用接口,將三個公共字段抽取出來,再以接口類型對外暴露商品的聚合查詢節點:ide
interface Item {
id: ID!
name: String!
price: Float!
}
type Drinks implements Item{ ... }
type Book implements Item{ ... }
type ElectricalEquipment implements Item{ ... }
type Query {
'''
商品列表,支持按商品名查詢
'''
items(name: Sring): [Item]
}
複製代碼
而對於客戶端來講,針對接口節點的查詢,除了接口的屬性外,也支持查詢實現類的字段:函數
query {
items(name: 'coka') {
name
... on Drinks {
capacity
}
}
}
複製代碼
代碼片斷 ... on Drinks { capacity }
,被稱爲 Inline Fragments。 針對這段查詢,引擎會幫助判斷若是解析結果爲 Drinks
類型,則返回 capacity
字段;若是是其餘類型的商品,則不作進一步處理,不會返回 capacity
,也不報錯。有興趣的讀者,能夠到 GraphQL 接口示例代碼 看看。ui
注意,GraphQL 引擎沒有檢測類型的能力,開發者必須爲接口節點提供
resolveType
函數,以在運行時指定解析結果的類型!不然會報錯:spaAbstract type NamedEntity must resolve to an Object type at runtime for field Query.users with value { id: 1, name: \"foo\", age: 1, type: \"User\" }, received \"undefined\". Either the NamedEntity type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function. 複製代碼