Hi Alex,
(You didn't say which language you're using so I'll assume C++, but roughly
the same should apply in other languages.)
You don't need AnyPointer here. Cap'n Proto supports upcasting and
downcasting capabilities, as any inheritance heirarchy should. E.g. a
TextNode::Client can implicitly cast to Node::Client. Downcasting is
explicit: if you have a `Node::Client`, you can call
`cilent.castAs<TextNode>()` to get a `TextNode::Client`.
However, `castAs` doesn't actually verify the remote type. If you then call
a `TextNode`-specific method, and the remote object doesn't actually
implement `TextNode`, then you'll get an "unimplemented" exception back.
So, you probably want some way to determine the type without calling
methods to find out if they throw. How to do that is really up to you. One
option would be to have a big enum. Another would be to use type ID's --
e.g. you can do `capnp::typeId<TextNode>()` to get the `uint64_t` type ID
for TextNode. (Note `typeId<T>()` is a constant expression -- you can use
it in in a switch case.)
So you can have a method like:
getType @0 () -> (id :UInt64);
Things get more complicated, of course, if you have a multi-level
hierarchy, e.g. Node -> Button -> RadioButton. Now you need to send around
a list of types.
getTypes @0 () -> (ids :List(UInt64));
To avoid incurring a round trip to get the type, you might try to pass the
type (or list of types) along with the capabilities, like:
interface Node {
children @0 () -> (list :List(TypedNode));
}
struct TypedNode {
node @0 :Node;
type @1 :UInt64;
}
Cap'n Proto does not have any built-in way of communicating the type
because in the vast majority of use cases, it either isn't needed at all,
or there is a use-case-specific solution that is cheaper/better than the
general solution.
-Kenton
On Sat, May 11, 2019 at 9:44 AM <[email protected]> wrote:
> I'm new to statically typed languages in general, I'm doing this as a
> learning experience.
>
> I'm building a toy UI toolkit, and I want to create a tree of widgets.
> Something like
>
> interface Node {
> children @0 () -> (list :List(Node));
> }
>
> interface TextNode extends(Node) {
> //some textNode specific stuff
> }
>
> My problem is that I want a node to be able to contain anything that
> *implements* the node interfaces, even if it's a textNode, or an SVGNode,
> or whatever. Is there a way to do that without resorting to using
> AnyPointer or registering all my sub nodes in advance? Some provision for
> doing structural typing?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Cap'n Proto" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> Visit this group at https://groups.google.com/group/capnproto.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/capnproto/04478ec6-c647-4d3f-a981-dc1bc6da6cae%40googlegroups.com
> <https://groups.google.com/d/msgid/capnproto/04478ec6-c647-4d3f-a981-dc1bc6da6cae%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.
To view this discussion on the web visit
https://groups.google.com/d/msgid/capnproto/CAJouXQkCx38eiG1ohbGzUNFLkxoU7giNPwyivUKqE29YPsEJxw%40mail.gmail.com.