Как расширить тип в GraphQL? [Дубликат]

Рассмотрим мало endian архитектур: значения сначала сохраняются в младших байтах. Таким образом, для любого заданного целого без знака значения 0-255 сохраняются в первом байте значения. Доступ к низким 8 битам любого значения просто требует указателя на его адрес.

Таким образом, мы могли бы реализовать uint8 как класс. Мы знаем, что экземпляр uint8 - это один байт. Если мы выйдем из него и создадим uint16, uint32 и т. Д., Интерфейс останется тем же самым для целей абстракции, но самым важным изменением является размер конкретных экземпляров объекта.

Конечно, если бы мы реализовали uint8 и char, размеры могут быть одинаковыми, аналогично sint8.

Однако operator= из uint8 и uint16 собираются перемещать разные количества данных.

Чтобы создать Полиморфную функцию, мы должны либо иметь возможность:

a / принять аргумент по значению, скопировав данные в новое место правильного размера и макета, b / взять указатель на местоположение объекта, c / взять ссылку на экземпляр объекта,

Мы можем использовать шаблоны для достижения a, поэтому полиморфизм может работать без указателей и ссылок, но если мы не учитываем шаблоны, тогда рассмотрим, что произойдет, если мы реализуем uint128 и передаем его функции, ожидающей uint8? Ответ: 8 бит будут скопированы вместо 128.

Итак, если мы допустили, что наша полиморфная функция принимает uint128, и мы передали ей uint8. Если бы наш uint8, который мы копировали, к сожалению, был найден, наша функция попыталась бы скопировать 128 байт, из которых 127 были за пределами нашей доступной памяти -> crash.

Рассмотрим следующее:

class A { int x; };
A fn(A a)
{
    return a;
}

class B : public A {
    uint64_t a, b, c;
    B(int x_, uint64_t a_, uint64_t b_, uint64_t c_)
    : A(x_), a(a_), b(b_), c(c_) {}
};

B b1 { 10, 1, 2, 3 };
B b2 = fn(b1);
// b2.x == 10, but a, b and c?

В момент компиляции fn не было известно о B. Однако B получен из A, поэтому полиморфизм должен позволить нам называть fn с помощью B. Однако возвращаемый объект должен быть A, содержащий один int.

Если мы передадим экземпляр B этой функции, то мы вернемся, просто { int x; } без a, b, c.

Это «нарезка».

Даже с указателями и ссылками мы не избегаем этого бесплатно. Рассмотрим:

std::vector vec;

Элементы этого вектора могут быть указателями на A или что-то, полученное из A. Язык обычно решает это с помощью «vtable», небольшого дополнения к экземпляру объекта, который идентифицирует тип и предоставляет указатели на функции для виртуальных функций. Вы можете думать о нем как о чем-то вроде:

template
struct PolymorphicObject {
    T::vtable* __vtptr;
    T __instance;
};

Вместо каждого объекта, имеющего свой собственный vtable, классы имеют их, а экземпляры объектов просто указывают на соответствующую таблицу vtable.

Проблема теперь не нарезка, а правильность шрифта:

struct A { virtual const char* fn() { return "A"; } };
struct B : public A { virtual const char* fn() { return "B"; } };

#include 
#include 

int main()
{
    A* a = new A();
    B* b = new B();
    memcpy(a, b, sizeof(A));
    std::cout << "sizeof A = " << sizeof(A)
        << " a->fn(): " << a->fn() << '\n';
}          

http://ideone.com/G62Cn0

sizeof A = 4 a->fn(): B

Что мы должны иметь A http://ideone.com/Vym3Lp

, но опять же это копирование A в A :

struct A { int i; A(int i_) : i(i_) {} virtual const char* fn() { return "A"; } };
struct B : public A {
    int j;
    B(int i_) : A(i_), j(i_ + 10) {}
    virtual const char* fn() { return "B"; }
};

#include 
#include 

int main()
{
    A* a = new A(1);
    B* b = new B(2);
    *a = *b; // aka a->operator=(static_cast(*b));
    std::cout << "sizeof A = " << sizeof(A)
        << ", a->i = " << a->i << ", a->fn(): " << a->fn() << '\n';
}       

http://ideone.com/DHGwun

(i копируется, но B j теряется )

. Вывод здесь состоит в том, что указатели / ссылки требуются, потому что исходный экземпляр несет с собой информацию membership , с которой может взаимодействовать копирование.

что полиморфизм не полностью решен в C ++, и нужно осознавать их обязательство предоставлять / блокировать действия, которые могут вызвать нарезку.

1
задан kayla 22 February 2018 в 01:43
поделиться

1 ответ

Это невозможно в GraphQL, однако есть экспериментальный пакет, который может быть полезен для этой цели.

https://github.com/Sydsvenskan/node-graphql-partials

См. пример:

partial LinkFields {
  links(
    rel: String
    type: String
  ): [Link]
}

partial DocumentFields using LinkFields {
  uuid: ID!

  # The document type, such as x-im/article
  type: String
  # If specified, then a list of the products to which this document's availability is limited
  products: [String]
  # The human readable name of the document, often used publicly to identify the document
  title: String

  # The specific path on the web page where this document is publicly available
  path: String

  # A single metadata block
  metaBlock(
    # The specific metadata block type to get
    type: String
  ): MetadataBlock
}

interface Document using DocumentFields {}

type AuthorDocument implements Document using DocumentFields {}

Какой приводит к:

type AuthorDocument implements Document {
  links(
    rel: String
    type: String
  ): [Link]

  uuid: ID!

  # The document type, such as x-im/article
  type: String
  # If specified, then a list of the products to which this document's availability is limited
  products: [String]
  # The human readable name of the document, often used publicly to identify the document
  title: String

  # The specific path on the web page where this document is publicly available
  path: String

  # A single metadata block
  metaBlock(
    # The specific metadata block type to get
    type: String
  ): MetadataBlock
}

То, что вы также можете сделать, поскольку это всего лишь строки, это создать некоторые вспомогательные функции, которые изменяют строку и вставляют необходимые поля.

Если вы

https://github.com/graphql/graphql-js/issues/703

https://github.com/graphql/graphql-js/issues/703 / g8]

1
ответ дан Ash Belmokadem 17 August 2018 в 09:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: