0

I have a superclass named Message with the field String msgType and a sub-class named ConnectMessage that extends it, which contains the field String pos_X.

The constructor of ConnectMessage is:

public ConnectMessage(String msgType, String x){
    super(msgType);
    this.pos_X = x;}

Inside the main thread i call: clientMessage = Message.fromString(inputString); where fromString creates a ConnectMessage instance like this:

ConnectMessage cm = new ConnectMessage(str1, str2);
return cm;

But when in the main thread i call s = clientMessage.pos_X i get a compiler error, saying that there is no variable pos_X in class Message. How does inheritance work here and how can i fix that, so that the statement clientMessage.pos_X will mean pos_X defined in class ConnectMessage?

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
nikos
  • 2,893
  • 11
  • 30
  • 39

6 Answers6

3

It's pretty obvious:

you declared clientMessage as Message class. This class does not have a filed named pos_x.

If you want to access that field, you have to either:

  • pull up the pos_x field to the base class
  • cast clientMessage to ConnectMessage i.e. ((ConnectMessage)message).pos_x

Of course, I assume the field is public.

Regards

emesx
  • 12,555
  • 10
  • 58
  • 91
1

I have defined clientMessage as Message clientMessage

Thats the reason for your compilation error.

And pos_X is defined in ConnectMessage which extends Message, hence Message doesnt know the fields in ConnectMessage.

Approach to fix this issue:

  1. You will have to cast it like ((ConnectMessage)clientMessage).pos_X if you want to refer to it.
  2. Move pos_X to Message class (here you have to decide is pos_X generic enough to be moved to Message, if yes please move, if no, it is very much related to ConnectMessage and tomorrow if there is a new derived class say DisconnectMessage and pos_X wont be useful for it then dont move.
  3. Instead of creating Message clientMessage do this ConnectMessage clientMessage but then with this you are deviating from Program to Interface

How Does Inheritance Works Here

In inheritance subclass, child, derived class (call it whatever you are comfortable with) will extend(inherit) properties from Super Class, Parent Class.

To make it simpler and more easy to understand,

Child takes surname of Father but reverse is not true, on similar lines in OOP with inheritance, A derived class will inherit from Parent vice-versa is not-true.

So in context of your question ConnectMessage can see properties defined in Message (provided they are not private) but Message doesnt know about the internals of ConnectMessage.

Community
  • 1
  • 1
mprabhat
  • 20,107
  • 7
  • 46
  • 63
0

pos_X is ONLY a field in ConnectMessage, not in Message. If the type you are accessing is of type Message, then there isn't guaranteed to be a pos_X field. So, the compiler is warning you that it is not safe to access it.

You can either changer your declaration to type ConnectMessage, then access it that way, or change your inheritance.

Either way, this is an indication that you have done something wrong in your object model. Either pos_X is something that all Messages should have, OR pos_X is something that should be accessed in a more generic way that all Messages have, OR you somehow have knowledge that this particular Message is actually a ConnectMessage instance, and you haven't let the compiler know that.

rfeak
  • 8,124
  • 29
  • 28
0

Try declaring clientMessage as ConnectMessage clientMessage; instead.

flyingCaffine
  • 382
  • 1
  • 4
  • 9
0

Because you declared clientMessage with Message clientMessage; the compiler only knows for sure that it is a Message. Because of this, you can only access methods/fields defined in Message or its parents. Since ConnectMessage is a subtype, you would need to either declare clientMessage as a ConnectMessage or use a type cast:

if(message instanceof ClientMessage){
 ((ClientMessage)(message).pos_x;
}
Chris
  • 22,923
  • 4
  • 56
  • 50
0

From what I understand from the original question it is because you are labeling the clientMessage as a Message class. Therefore it can only use variables and methods within the Message class.

To fix this you can make this method in Message

public String getPos_X() { return "Sorry, this is just a Message object!"; }

And then override it in ConnectMessage

public String getPos_X() { return pos_X; }

This way you can call the method even with a Message object and it will return the right value as long as it is truly a ConnectMessage object.

Or if it's of no importance to you to have a Message object instead of a ConnectMessage object

((ConnectMessage)clientMessage).pos_X;
Austin Heerwagen
  • 653
  • 3
  • 12