digitalmars.D.learn - Inheriting class checks
- IchorDev (11/11) Aug 09 2023 A common pattern when working with inheriting classes or classes
- Arafel (20/32) Aug 10 2023 I faced this issue recently. In my case, and I think it's the most
- Steven Schveighoffer (12/24) Aug 10 2023 The *correct* way is to use a cast. Though, that can be overridden.
- Nick Treleaven (21/31) Aug 11 2023 To avoid both the opCast and the casting away const problem,
- IchorDev (4/6) Aug 12 2023 But what if `y` is `const`, or even `immutable`? How is it
- Nick Treleaven (4/10) Aug 12 2023 Because the cast removes the type qualifier, so could allow
- Dom DiSc (6/14) Aug 12 2023 I hate this. Why don't we have an "unqual cast" (a cast that
- Richard (Rikki) Andrew Cattermole (7/7) Aug 12 2023 This should work:
A common pattern when working with inheriting classes or classes that implement an interface is to use the base class or interface as a generic type: ``` interface Thing{} class OtherThing: Thing{} Thing[] array = [new OtherThing(), …]; ``` So how do people usually check if an item in `array` is a sub-class of `Thing`, or implements an interface that inherited from `Thing`? Is `typeid` the only way to do this?
Aug 09 2023
On 10/8/23 7:59, IchorDev wrote:A common pattern when working with inheriting classes or classes that implement an interface is to use the base class or interface as a generic type: ``` interface Thing{} class OtherThing: Thing{} Thing[] array = [new OtherThing(), …]; ``` So how do people usually check if an item in `array` is a sub-class of `Thing`, or implements an interface that inherited from `Thing`? Is `typeid` the only way to do this?I faced this issue recently. In my case, and I think it's the most common case, I didn't care what exact type it was, I just wanted to make sure it was `OtherThing`. If it wasn't, the exact type didn't really matter. If that's also your case, you can just cast to the type you need, and check for `null`. My case was like this: ```d interface Thing{ void foo(Thing[] array); } class OtherThing: Thing{ override void foo(Thing[] array) { foreach (thing; array) { auto otherThing = cast (OtherThing) thing; assert(otherThing, "Wrong type in `array`: " ~ typeid(thing).toString); // Do something here } } } ```
Aug 10 2023
On 8/10/23 1:59 AM, IchorDev wrote:A common pattern when working with inheriting classes or classes that implement an interface is to use the base class or interface as a generic type: ``` interface Thing{} class OtherThing: Thing{} Thing[] array = [new OtherThing(), …]; ``` So how do people usually check if an item in `array` is a sub-class of `Thing`, or implements an interface that inherited from `Thing`? Is `typeid` the only way to do this?The *correct* way is to use a cast. Though, that can be overridden. A very nice pattern in D is: ```d if(auto x = cast(DerivedTypeOrInterface)y) { // use x } ``` This also can be dangerous if e.g. `y` in the future becomes `const`. This is one place where pattern matching would be very useful. In fact, we already do it for try/catch, I don't see why we can't do it in general. -Steve
Aug 10 2023
On Thursday, 10 August 2023 at 15:25:41 UTC, Steven Schveighoffer wrote:The *correct* way is to use a cast. Though, that can be overridden. A very nice pattern in D is: ```d if(auto x = cast(DerivedTypeOrInterface)y) { // use x } ``` This also can be dangerous if e.g. `y` in the future becomes `const`.To avoid both the opCast and the casting away const problem, perhaps std.conv should have: ```d D derived(D, B : Object)(B base) if (is(D : B) && !__traits(compiles, base.opCast!D)) { return cast(D)base; } alias E = Exception; void main() { Object o = new E("hi"); E c = o.derived!E; assert(c.msg == "hi"); } ``` There's probably some way to statically enforce that `B` has `extern(D)` linkage, `derived` could enforce that too. (`extern(C++)` classes don't have RTTI).
Aug 11 2023
On Thursday, 10 August 2023 at 15:25:41 UTC, Steven Schveighoffer wrote:This also can be dangerous if e.g. `y` in the future becomes `const`.But what if `y` is `const`, or even `immutable`? How is it dangerous?
Aug 12 2023
On Saturday, 12 August 2023 at 09:32:14 UTC, IchorDev wrote:On Thursday, 10 August 2023 at 15:25:41 UTC, Steven Schveighoffer wrote:Because the cast removes the type qualifier, so could allow mutation of immutable data. In safe code I expect that situation would error.This also can be dangerous if e.g. `y` in the future becomes `const`.But what if `y` is `const`, or even `immutable`? How is it dangerous?
Aug 12 2023
On Thursday, 10 August 2023 at 15:25:41 UTC, Steven Schveighoffer wrote:A very nice pattern in D is: ```d if(auto x = cast(DerivedTypeOrInterface)y) { // use x } ``` This also can be dangerous if e.g. `y` in the future becomes `const`.I hate this. Why don't we have an "unqual cast" (a cast that changes the type but leave all qualifiers unchanged)? That should not be complicated to implement, but would be useful very often.
Aug 12 2023
This should work: ```d import std.traits : CopyTypeQualifiers; if(auto x = cast(CopyTypeQualifiers!(typeof(y), DerivedTypeOrInterface))y) { // use x } ```
Aug 12 2023