Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Jack Stouffer via Digitalmars-d-learn

On Thursday, 13 August 2015 at 20:28:33 UTC, Adam D. Ruppe wrote:
On Thursday, 13 August 2015 at 20:23:56 UTC, Jack Stouffer 
wrote:
As far as I can tell, there is no way to know the actual type 
of each of the objects in the list to be able to print:


Cast it to Object first, then do the typeid and it will get the 
dynamic class type. Since Parent is an interface, typeid works 
differently.


I wrote about this in more detail recently here:
http://stackoverflow.com/questions/31563999/how-to-get-classinfo-of-object-declared-as-an-interface-type/31564253#31564253


Thanks, that worked, and based on your answer, I was able to fix 
my real problem: dynamically calling different methods on each 
object in the list based on its type. So, using the above code as 
an example, I am able to call method if the object is of type A 
and method2 if the object is of type B:


interface Parent {
void method();
}

class A : Parent {
void method() {}

this() {}
}

class B : Parent {
void method() {}
void method2() {}

this() {}
}

void main() {
import std.stdio;
import std.string;

Parent[] parent_list = [];
parent_list ~= new A();
parent_list ~= new B();

foreach (item; parent_list) {
string class_name = (cast(Object) 
item).classinfo.name;

if (class_name == test.A) {
(cast(A) item).method();
} else if (class_name == test.B) {
(cast(B) item).method2();
}
}
}

This is a dirty hack, but I don't care, it works :)


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Jack Stouffer via Digitalmars-d-learn

On Thursday, 13 August 2015 at 22:20:35 UTC, Justin Whear wrote:

foreach (item; parent_list) {
  if (auto asA = cast(A)item) {
asA.method();
  } else if (auto asB = cast(B)item) {
asB.method2();
  }
}


On Thursday, 13 August 2015 at 22:20:35 UTC, Justin Whear wrote:

Thanks Justin and rumbu, that makes the code a lot more readable.


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread rumbu via Digitalmars-d-learn

On Thursday, 13 August 2015 at 21:42:54 UTC, Jack Stouffer wrote:

Thanks, that worked, and based on your answer, I was able to 
fix my real problem: dynamically calling different methods on 
each object in the list based on its type. So, using the above 
code as an example, I am able to call method if the object is 
of type A and method2 if the object is of type B:


interface Parent {
void method();
}

class A : Parent {
void method() {}

this() {}
}

class B : Parent {
void method() {}
void method2() {}

this() {}
}

void main() {
import std.stdio;
import std.string;

Parent[] parent_list = [];
parent_list ~= new A();
parent_list ~= new B();

foreach (item; parent_list) {
string class_name = (cast(Object) 
item).classinfo.name;

if (class_name == test.A) {
(cast(A) item).method();
} else if (class_name == test.B) {
(cast(B) item).method2();
}
}
}

This is a dirty hack, but I don't care, it works :)


It works as long as your module is called test.

I think this is a better approach:

foreach (item; parent_list) {
if (auto a = cast(A)item)
a.method();
else if (auto b = cast(B)item)
b.method2();
}



Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Jack Stouffer via Digitalmars-d-learn

On Friday, 14 August 2015 at 00:06:33 UTC, Adam D. Ruppe wrote:
On Thursday, 13 August 2015 at 23:48:08 UTC, Jack Stouffer 
wrote:
In my code, the list can have 20-30 different types of classes 
in it all inheriting from the same interface, and it doesn't 
make sense for all of those classes to implement a method that 
is very specific to one of the classes.



I don't want to get too far into this since I haven't seen your 
code, but the function that uses this list might itself be a 
candidate for addition to the interface, or a second interface 
with that method that all the classes also inherit from 
(remember you can only inherit from one class in D, but you can 
implement as many interfaces as you want).


The code in question is a collision resolver in a 2D game that I 
am making. The list is a list of all of the drawable objects that 
the object could be colliding with. After collision is checked on 
each of the possible collisions, the object is placed at the last 
position where it was not colliding. I am using the cast in the 
enemy resolver where each collision is then checked to see if the 
collision was with the player, and if it was, the player is then 
given damage.


-
class Blob : Enemy {
...

final override void resolveCollisions() {
import player : Player;

//check for collision
Entity[] possible_collisions = 
this.state_object.getPossibleCollisions(this);

Entity[] collisions = [];

foreach (ref entity; possible_collisions) {
// discount any Rect that is equal to the player's, 
as it's probably

// the players bounding box
if (this.boundingBox != entity.boundingBox 
this.boundingBox.intersects(entity.boundingBox)) {
collisions ~= entity;
}
}

if (collisions.length  0) {
// If we collided with something, then put position 
back to its

// original spot
this.position = this.previous_position;

// If we collided with the player, give the player 
damage

foreach (collision; collisions) {
// Check to see if the object collided was a 
player by testing the
// result of the cast, which will return null if 
unsuccessful

if (auto player = cast(Player) collision) {
player.damagePlayer(5, this.position, 
this.mass);

}
}
}
}
}


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 August 2015 at 23:48:08 UTC, Jack Stouffer wrote:
In my code, the list can have 20-30 different types of classes 
in it all inheriting from the same interface, and it doesn't 
make sense for all of those classes to implement a method that 
is very specific to one of the classes.



I don't want to get too far into this since I haven't seen your 
code, but the function that uses this list might itself be a 
candidate for addition to the interface, or a second interface 
with that method that all the classes also inherit from (remember 
you can only inherit from one class in D, but you can implement 
as many interfaces as you want).


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Ali Çehreli via Digitalmars-d-learn

On 08/13/2015 04:48 PM, Jack Stouffer wrote:

On Thursday, 13 August 2015 at 22:49:15 UTC, Adam D. Ruppe wrote:

On Thursday, 13 August 2015 at 21:42:54 UTC, Jack Stouffer wrote:

dynamically calling different methods on each object in the list
based on its type.


The cleanest OO way of doing that is to put the methods you need in
the interface and always call it through that. Then there's no need to
cast and each child class can implement it their own way.


This really doesn't make sense in the context that I am using this code
in. The above code is a very reduced test case. In my code, the list can
have 20-30 different types of classes in it all inheriting from the same
interface, and it doesn't make sense for all of those classes to
implement a method that is very specific to one of the classes.


Enter the visitor pattern (or its variant 'acyclic visitor pattern'). 
Although, with 20-30 classes, it will be nasty to use.. :( So, 
downcasting like suggested seems to be the best option here.


Ali



Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 August 2015 at 21:42:54 UTC, Jack Stouffer wrote:
dynamically calling different methods on each object in the 
list based on its type.


The cleanest OO way of doing that is to put the methods you need 
in the interface and always call it through that. Then there's no 
need to cast and each child class can implement it their own way.


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Justin Whear via Digitalmars-d-learn
On Thu, 13 Aug 2015 21:42:52 +, Jack Stouffer wrote:

  foreach (item; parent_list) {
  string class_name = (cast(Object)
 item).classinfo.name;
  if (class_name == test.A) {
  (cast(A) item).method();
  } else if (class_name == test.B) {
  (cast(B) item).method2();
  }
  }
 }
 
 This is a dirty hack, but I don't care, it works :)

Casting actually performs this check for you, returning null if the 
object can't be casted, so I'd do this:

foreach (item; parent_list) {
  if (auto asA = cast(A)item) {
asA.method();
  } else if (auto asB = cast(B)item) {
asB.method2();
  }
}


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Jack Stouffer via Digitalmars-d-learn

On Thursday, 13 August 2015 at 22:49:15 UTC, Adam D. Ruppe wrote:
On Thursday, 13 August 2015 at 21:42:54 UTC, Jack Stouffer 
wrote:
dynamically calling different methods on each object in the 
list based on its type.


The cleanest OO way of doing that is to put the methods you 
need in the interface and always call it through that. Then 
there's no need to cast and each child class can implement it 
their own way.


This really doesn't make sense in the context that I am using 
this code in. The above code is a very reduced test case. In my 
code, the list can have 20-30 different types of classes in it 
all inheriting from the same interface, and it doesn't make sense 
for all of those classes to implement a method that is very 
specific to one of the classes.


How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Jack Stouffer via Digitalmars-d-learn

Given:


interface Parent {
void method();
}

class A : Parent {
void method() {}

this() {}
}

class B : Parent {
void method() {}
void method2() {}

this() {}
}

void main() {
import std.stdio;

Parent[] parent_list = [];
parent_list ~= new A();
parent_list ~= new B();

foreach (item; parent_list) {
writeln(typeid(item));
}
}


With 2.068, it will output:

test.Parent
test.Parent

As far as I can tell, there is no way to know the actual type of 
each of the objects in the list to be able to print:


test.A
test.B

Are there any workarounds for this?

Also, this fails to compile when it doesn't look like it should:

interface Parent {
void method();
}

class A : Parent {
void method() {}

this() {}
}

class B : Parent {
void method() {}
void method2() {}

this() {}
}

void main() {
import std.stdio;

Parent[] parent_list = [new A(), new B()];

foreach (item; parent_list) {
writeln(typeid(item));
}
}



Thanks.


Re: How do I find the actual types of the elements in a list of classes?

2015-08-13 Thread Adam D. Ruppe via Digitalmars-d-learn

On Thursday, 13 August 2015 at 20:23:56 UTC, Jack Stouffer wrote:
As far as I can tell, there is no way to know the actual type 
of each of the objects in the list to be able to print:


Cast it to Object first, then do the typeid and it will get the 
dynamic class type. Since Parent is an interface, typeid works 
differently.


I wrote about this in more detail recently here:
http://stackoverflow.com/questions/31563999/how-to-get-classinfo-of-object-declared-as-an-interface-type/31564253#31564253

it is a bit of a FAQ, but there's a solid reason behind the 
behavior.




Also, this fails to compile when it doesn't look like it should:


I believe that's a well-known bug, the array literal tries to 
type it all to the first element instead of looking for the 
common types of all elements.


You could explicitly cast to the interface if you needed to, I 
believe just casting the first one will cause it to do the rest 
automatically.