Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

dynamic casting?

Posted on 1998-02-10
15
13,786 Views
Last Modified: 2011-08-18
Is there a way to dynamically cast an object?
I already know that the object valid
and that I have the class name.

  method(Object o) {
     (fill in here)o).afield = 55;
  }
0
Comment
Question by:hank1
  • 6
  • 4
  • 4
  • +1
15 Comments
 
LVL 2

Expert Comment

by:shogi
ID: 1232995
YES!  

class A extends Object
{
  public int afield;
  // ...
}

class B
{
   void method(Object o)
   {
     if (o intanceof A)  // optional, just for protection
     {
         ((A)o).afield = 55;
     }
   }

}

  You can cast if you be sure that your object exist!  And you not force to use the if with the instanceof, but it's a protection and if you know that it's a valid object you can cast it directly.



0
 
LVL 1

Author Comment

by:hank1
ID: 1232996
I mean dynamically as in I don't have (A) until
runtime.  Using instanceof means that I know what
I have and "switch" to the cast I want. The only thing
I know is that any object I get will have a field
named serialNumber, and I want to
((dynamically cast)o).serialNumber = 1231231;
In another way say I pass
a class type-name (how?) along with the mystery object like

  method (class_name, mysteryO)

  then I want to cast
    (class_name)mysteryO

Follow-up ..
Does an 'object' have a way of discovering
its own name - I see something called Object.getClass()
but have no idea how to use it.  Seems like it may be a
way for an upcasted object to downcast itself.


0
 
LVL 2

Expert Comment

by:shogi
ID: 1232997
No, you can't do that like this...but if you use Java 1.1..
java.lang.reflect will help you to do everything you need in run-time.  I put one simple example :


import java.awt.*;
import java.applet.*;
import java.lang.reflect.*;

class A extends java.lang.Object
{
   public int Variable;  
   
   A(int n)
   {
      Variable = n;
   }

}

class B extends java.lang.Object
{
   public int Variable;  
   
   B(int n)
   {
      Variable = n;
   }

}

public class Applet1 extends Applet
{
      public void init()
      {
            // Take out this line if you don't use symantec.itools.net.RelativeURL or symantec.itools.awt.util.StatusScroller
            symantec.itools.lang.Context.setApplet(this);
      
            // This code is automatically generated by Visual Cafe when you add
            // components to the visual environment. It instantiates and initializes
            // the components. To modify the code, only use code syntax that matches
            // what Visual Cafe can generate, or Visual Cafe may be unable to back
            // parse your Java file into its visual environment.
            //{{INIT_CONTROLS
            setLayout(null);
            setSize(426,345);
            label1 = new java.awt.Label("text");
            label1.setBounds(48,12,274,24);
            add(label1);
            button1 = new java.awt.Button();
            button1.setActionCommand("button");
            button1.setLabel("Class A");
            button1.setBounds(24,252,144,68);
            button1.setBackground(new Color(12632256));
            add(button1);
            button2 = new java.awt.Button();
            button2.setActionCommand("button");
            button2.setLabel("Class B");
            button2.setBounds(228,252,141,71);
            button2.setBackground(new Color(12632256));
            add(button2);
            label2 = new java.awt.Label("text");
            label2.setBounds(48,48,278,24);
            add(label2);
            label3 = new java.awt.Label("text");
            label3.setBounds(48,84,288,24);
            add(label3);
            label4 = new java.awt.Label("text");
            label4.setBounds(48,120,288,24);
            add(label4);
            label5 = new java.awt.Label("text");
            label5.setBounds(48,156,288,24);
            add(label5);
            label6 = new java.awt.Label("text");
            label6.setBounds(48,192,288,24);
            add(label6);
            //}}
      
            //{{REGISTER_LISTENERS
            SymMouse aSymMouse = new SymMouse();
            button1.addMouseListener(aSymMouse);
            button2.addMouseListener(aSymMouse);
            //}}
      }

    void TheMethod(Object obj)
    {
        int tVariable=0;
        Class theClass = obj.getClass();
     
        Field ref[] = theClass.getFields();
       
        label1.setText(ref[0].toString());
           
        label2.setText(ref[0].getDeclaringClass().toString());

        label3.setText(ref[0].getName());  
       
        label4.setText(theClass.getSuperclass().getName());

        label5.setText(Modifier.toString(theClass.getModifiers()));
 
        try
        {
          Field result = theClass.getField("Variable");
          tVariable = result.getInt(obj);
        }
        catch(NoSuchFieldException e)
        {}
        catch(IllegalAccessException e)
        {}
        label6.setText("The value tVariable is " + tVariable);
    }

      
      //{{DECLARE_CONTROLS
      java.awt.Label label1;
      java.awt.Button button1;
      java.awt.Button button2;
      java.awt.Label label2;
      java.awt.Label label3;
      java.awt.Label label4;
      java.awt.Label label5;
      java.awt.Label label6;
      //}}

      class SymMouse extends java.awt.event.MouseAdapter
      {
            public void mouseClicked(java.awt.event.MouseEvent event)
            {
                  Object object = event.getSource();
                  if (object == button1)
                        button1_MouseClick(event);
                  else if (object == button2)
                        button2_MouseClick(event);
            }
      }

      void button1_MouseClick(java.awt.event.MouseEvent event)
      {
            A a = new A(65);
        TheMethod(a);

      }

      void button2_MouseClick(java.awt.event.MouseEvent event)
      {
        B b = new B(66);
       
        TheMethod(b);
      }
}

0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
LVL 1

Author Comment

by:hank1
ID: 1232998
looks good - let me digest it.  I'll get back to you.
Thanks alot!
0
 
LVL 1

Author Comment

by:hank1
ID: 1232999
Seems that reflection methods cannot obtain a friendly
field only public ones, while casting will access friendly
members.  Why do you think they would allowing casting
privledges not allow here?

    Class moClass = mo.getClass();
    if (globalCommand == cmd.moduleSerialNumber) {
      System.out.println("This is a serial number request");
      try {
        Field moField = moClass.getField("moduleSerialNumber");
        moField.set(mo, new String("thisIsATest"));
      } catch (Exception e) {
        e.printStackTrace();
        return false;
      }
      return false;
    }

I cannot allow the objects fields to be public so I'll have
to come up with something else.  Come back and I'll give
you your points.  

ps - any ideas on this?   If not I am going to have to create
a complete list of possible classes passed to this method and
to instance test nuts.
Thanks shogi!


0
 
LVL 3

Expert Comment

by:gwalters
ID: 1233000
If I understand what you're doing, may I suggest using an Interface?  That's what they're there for.

0
 
LVL 2

Expert Comment

by:shogi
ID: 1233001
You can't cast with a variable
{
 method (class_name, mysteryO)
      then I want to cast
  (class_name)mysteryO
}

Interface will not resolve your problem, because you don't know your class before calling.

You unique change it's to use java.lang.reflect,  but if you can allow the field to be public.  The better way it's to add in each  class you have moduleSerialNumber, a method to get it.  And after that you just have to access this method with reflect.

like in your class
 public int getModuleSerialNumber() (return moduleSerialNumber;}

// Naturally here all in try / catch

Method GetRef = TheClass.getMethod("getModuleSerialNumber", TheClass);

Object argGet[] = {};  //empty argument
Integer MymoduleSerialNumber = (Integer) GetRef.invoke(obj, argGet);
int LaValeurModuleSerialNumber = MymoduleSerialNumber.intValue();


0
 
LVL 3

Expert Comment

by:gwalters
ID: 1233002
shogi:

You obviously don't understand Interfaces.  You say "you don't know your class before calling".  THAT'S THE POINT OF AN INTERFACE.  You don't have to know the class, only that it implements the method you are about to call.
0
 
LVL 1

Author Comment

by:hank1
ID: 1233003
interface? - I'll check it out in this respect. I have only
used interfaces as a design tool - for creating
things like instruments that must impliment methods like
on() off() stop() and go()  - simple stuff that can be passed
around.

I really don't see now
how an interface will work for me and how it will allow me
access to friendly fields.  Thanks for the feedback shogi and
gwalters!  I'LL BE BACK.
0
 
LVL 5

Expert Comment

by:fontaine
ID: 1233004
You have to use interfaces, indeed.

Example:

// definition of the interface

public interface myInterface
{
 public String getMessage();
}

---

// two examples of classes implementing the interface

public class A implements myInterface
{
 ...

 public String getMessage()
 {
  return "Message from A";
 }
}

public class B implements myInterface
{
 ...

 public String getMessage()
 {
  return "Message from B";
 }
}

Now, dynamic casting...

void method(Object o)
{
// the following line performs the casting. As both A and B
// implements myInterface, the "cast" will succeed. Otherwise,
// it will fail.

 myInstance i = (myInstance)o;

 String message = i.getMessage();

// for A, you will have "Message from A"
// for B, you will have "Message from B"

 System.out.println(message)

 return;
}

0
 
LVL 1

Author Comment

by:hank1
ID: 1233005
I understand how an interface guarantees a static cast but I
don't see how it helps in accessing a friendly field dynamically.
If all my classes impliment X, then I'll be ok. But all the
classes don't. I really only
know one thing - they have a friendly field.
I think I am with shogi and believe it cannot be done.

Again, it is strange as to why access privileges differ
between a 'static' cast operation (MyKnownClassType)o and
a 'dynamic' cast using Class and Field methods in my
example above.
Still working it but about ready to surrender.
Thanks for the feedback!

0
 
LVL 3

Expert Comment

by:gwalters
ID: 1233006
You can't use an interface to access a variable (what you call a friendly field), only a method.

You need to have your interface include two methods:

Object getAField()
void setAField(Object)

It's slightly less efficient than accessing the variable directly, but it allows you to do what you want and it's better programming.

The other alternative is to have all your classes extend a single class, which contains the variable you want access to.  The problem here is that they may not extend any other class (no multiple inheritance in Java).
0
 
LVL 1

Author Comment

by:hank1
ID: 1233007
I have the advantage that all the classes belong to the
same package.
 
Ok, I surrender!  For some unknown reason the the Class and Field
version of my dynamic cast attempt will not allow access
where a 'static' cast will.  I've tried everything I
know.  Thankyou all for your help.   He was first, so,
shogi come back and get you points.
0
 
LVL 2

Accepted Solution

by:
shogi earned 50 total points
ID: 1233008
I pass GO and grab the points :-)

You best solution it's with reflect, direct access to public variable or method, and it's work very well ... But sorry none for friendly field...



 
0
 
LVL 3

Expert Comment

by:gwalters
ID: 1233009
As long as I never have to maintain any of your code, do whatever you want.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to implement Singleton Design Pattern in Java.
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question