[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 13813
  • Last Modified:

dynamic casting?

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
hank1
Asked:
hank1
  • 6
  • 4
  • 4
  • +1
1 Solution
 
shogiCommented:
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
 
hank1Author Commented:
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
 
shogiCommented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
hank1Author Commented:
looks good - let me digest it.  I'll get back to you.
Thanks alot!
0
 
hank1Author Commented:
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
 
gwaltersCommented:
If I understand what you're doing, may I suggest using an Interface?  That's what they're there for.

0
 
shogiCommented:
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
 
gwaltersCommented:
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
 
hank1Author Commented:
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
 
fontaineCommented:
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
 
hank1Author Commented:
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
 
gwaltersCommented:
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
 
hank1Author Commented:
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
 
shogiCommented:
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
 
gwaltersCommented:
As long as I never have to maintain any of your code, do whatever you want.
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 6
  • 4
  • 4
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now