0

Below is the proto code,

message Animal {
    optional string name = 1;
    optional int32 age = 2;  
}    

message Dog{
    optional string breed = 1;
}

Then the sample class using the above proto

public class InheritanceTest {

    public static void main(String[] args){
        Dog dog = Dog.getDefaultInstance();
        printAnimalName(dog.getAnimal());
    }

    public static void printAnimal(Animal animal){
        Dog dog = (Dog)animal; // Not at all possible right!
    }

} 

Is up-casting possible only by having an instance of dog as "required" in animal? or Is there any other way of upcasting?

Aarish Ramesh
  • 6,745
  • 15
  • 60
  • 105

1 Answers1

1

First, to be clear: "Upcasting" means casting a Dog to an Animal. "Downcasting" means casting an Animal to a Dog. Your question is about how to upcast, but your example appears to be about downcasting. I'll try to answer both.

In my answer to your other question, I presented three options for emulating inheritance with protobufs.

Option 1 makes upcasting easy but does not allow for downcasting.

Options 2 and 3 make downcasting possible, but do not support upcasting.

If you need to be able to both upcast and downcast, then you need to use option 2 or 3, but always pass around an Animal as simply an Animal. That is, if you have a function which only works on Dog, but needs to access some of the members of Animal as well, it must take Animal as its argument. The function's documentation should state that even though the argument type is Animal, the argument must have the dog field (or extension) set, i.e. it must actually be a Dog. You should throw an IllegalArgumentException otherwise.

Editorial: I know this is not a very satisfying answer. Protocol Buffers does not implement true inheritance because we couldn't come up with any design that seemed reasonable. The requirements of backwards- and forwards-compatibility on the wire make this problem a lot more complicated than it may seem. In practice, though, we've found that inheritance is rarely actually what you want anyway, and one of the options I presented usually works fine. In my opinion, inheritance makes sense for interfaces (i.e. collections of methods with behavior), but not for messages (i.e. collections of fields containing simple data).

Community
  • 1
  • 1
Kenton Varda
  • 41,353
  • 8
  • 121
  • 105
  • I jus thought upcast and downcast mean the other way, thanks for clarifying!.. thn getting to know ab these inadequecies/complications in casting when i use inheritance in protos, I have decided not to bring these kind of relations among proto messages and keep it to the java wrappers which wrap the protos! – Aarish Ramesh Feb 02 '14 at 19:02
  • Then I have a doubt regarding updating a repeated field of a message type in a super message type. Is it possible to edit an added repeated field of a message type? I looked into the java source code generated from proto and found that a repeated field is built before getting added and so it's not possible. Is it possible by any chance? – Aarish Ramesh Feb 04 '14 at 18:10
  • If you have a repeated field `foo`, you can call `getFooBuilder()` or `addFooBuilder()` to get a `Builder` for an element, which you can then modify. However, if you call `addFoo(someBuilder)`, and then you modify `someBuilder` after the call, those changes won't affect the added value. (You can of course call `getFooBuilder(getFooCount() - 1)` to get a `Builder` for the element you just added, which you can then use to modify it.) – Kenton Varda Feb 05 '14 at 09:23
  • addFooBuilder() does the job for me thank you. Please answer this final question on the performance of builder as general data object, http://stackoverflow.com/questions/21586250/performance-analysis-of-using-protobuff-builders-as-general-data-object – Aarish Ramesh Feb 05 '14 at 19:06