digitalmars.D.learn - strettosis tutanota.com
- Stretto (30/30) Jun 09 2016 I have some class like
- Stretto (9/9) Jun 09 2016 Ultimately what I want to do is access a member
- Mike Parker (44/64) Jun 09 2016 That's just the nature of working with class hierarchies. A
- ArturG (19/19) Jun 10 2016 you could also use a simple wrapped cast
I have some class like class bar { } class foo : bar { bar[] stuff; } and have another class class dong : bar { int x; } Now sometimes stuff will contain dong's, but I cannot access its members it without a cast. fooo.stuff[0].x // invalid because bar doesn't contain x; Hence, ((cast(dong)foo.stuff[0]).x is the normal way with a possible type check. But in my case I will never mix different types in stuff and will always use it properly or do type checking in the cases I might mix. Rather than add a dong[] dongs; to foo, which increases the size of foo and wastes memory just to prevent the cast, I'm curious if there is any other way to solve this problem? I simply want to do foo.stuff[0].x and have foo.stuff[0] be treated as an image. Is an opDispatch and/or opIndex required or is there some alias trick that can be used? I'd rather access like foo.dongs[0].x without defining a dong array directly in foo, but simply alias to stuff with an implicit cast to dong.
Jun 09 2016
Ultimately what I want to do is access a member foo.Dongs[i]; Where Dongs is essentially a "view" in to the Bars array and only accesses types of type Dong. It seems one can't do both an override on a name("Dongs") and an index on the overridden name(`[i]`)? It is not appropriate to use foo.Dongs(i). A clear example: https://dpaste.dzfl.pl/7ea52a0f21ce
Jun 09 2016
On Thursday, 9 June 2016 at 22:19:33 UTC, Stretto wrote:I have some class like class bar { } class foo : bar { bar[] stuff; } and have another class class dong : bar { int x; } Now sometimes stuff will contain dong's, but I cannot access its members it without a cast. fooo.stuff[0].x // invalid because bar doesn't contain x; Hence, ((cast(dong)foo.stuff[0]).x is the normal way with a possible type check. But in my case I will never mix different types in stuff and will always use it properly or do type checking in the cases I might mix.That's just the nature of working with class hierarchies. A Derived is always a Base, but a Base might not be a Derived. If your Bar array in Foo will always hold only one type of Bar, then you can parameterize Foo with a type: class Bar { } // Only accept types that are implicitly convertible to Bar class Foo(T : Bar) : Bar { T[] stuff; } class Dong : Bar { int x; this(int x) { this.x = x; } } void main() { import std.stdio; auto foo = new Foo!Dong(); foo.stuff ~= new Dong(10); writeln(foo.stuff[0].x); } Another option is to use a parameterized getter, which is somewhat cleaner than a cast. class Foo : Bar { Bar[] stuff; T get(T : Bar)(size_t index) { return cast(T)stuff[index]; } } void main() { import std.stdio; auto foo = new Foo(); foo.stuff ~= new Dong(10); writeln(foo.get!Dong(0).x); }
Jun 09 2016
you could also use a simple wrapped cast Ret castTo(Ret, T)(T t) if(is(T == class)) { return cast(Ret) t; } then do foo.stuff[0].castTo!Dong.x.writeln; and if you want to guard the access you could try foo.stuff[0].castTo!Dong.cc!((d){d.x = 5;}); cc is an alias for checkCall which is a template you can find here http://forum.dlang.org/thread/ltalqpmpscdoziserqqx forum.dlang.org, it treats Type.init as false and ignores the call to fun. but its not restricted to nullables only e.g. float someF; iota(0, someF).writeln; // normally would throw an AssertError someF.cc!(f => iota(0, f)).writeln; // returns an empty range without calling iota, as float.nan is treated as false. same as 0.0.cc!(f => iota(0, f)).writeln;
Jun 10 2016