88192

What is the advantage to declaring an object of one type as in instance of another? [duplicate]

Question:

<blockquote>

<strong>Possible Duplicate:</strong><br /><a href="https://stackoverflow.com/questions/4447924/what-does-base-b2-new-child-signify" rel="nofollow">What does Base b2 = new Child(); signify?</a>

</blockquote>

I'm a Java beginner. I understand the concepts of class inheritance, but there's one thing I don't quite understand. I'm reading through Java for Dummies, and it's explaining polymorphism. It gives this code as an example:

class Player { public void move() {... class BetterPlayer extends Player { public void move() {... public class TicTacToeApp { public static void main(String[] args) { Player p1 = new Player(); Player p2 = new BetterPlayer(); playTheGame(p1, p2); } public static void playTheGame(Player p1, Player p2) { p1.move(); p2.move(); } }

Why was p2 created as a Player object? Here's my understanding:

If p2 were a BetterPlayer object (declared like this: BetterPlayer p2 = new BetterPlayer...):<br /> -upcasting is automatic, so it would still work with the playTheGame method<br /> -p2 can be used by any methods requiring a BetterPlayer object

But since it was created as a Player object, now any time p2 is used by a method requiring a BetterPlayer object, it must be explicitly cast to a BetterPlayer object, right? That seems like more work with no benefit, so I'm guessing there has to be some benefit to doing it that way; what is it?

Answer1:

The variable p2 was not created as a Player object. It's a reference that points to a BetterPlayer object.

Regardless whether p2 is declared as a Player or BetterPlayer reference, it can be used as a Player reference.

An advantage of declaring it as a Player is that you are prevented from coupling any code that works only with BetterPlayer, keeping open the option of using the code for another subclass option in the future -- e.g., BestPlayer.

Answer2:

Any Player can, logically speaking, play the game (that's what makes the Player a player); so playTheGame should not care that the Player is a BetterPlayer. The advantage of polymorphism is exactly that playTheGame is not forced to care about something that it shouldn't care about.

We don't cause a real problem by assigning the BetterPlayer to a Player variable (p2) because if we knew we were going to call a bunch of functions that required a BetterPlayer specifically, then we simply <strong>wouldn't do that</strong>. "Doctor, it hurts when I tell the type system to forget things that actually are important." In the current case, it isn't important, so we have no problem throwing away the specific type information.

But further, even if we declared p2 to be a BetterPlayer, we could still pass it to playTheGame without writing any casts. The upcast when calling the function would be implicit, and inside the function we don't need to downcast because we don't care if we have a BetterPlayer - since we're only using the base Player interface. And then again, a lot of the time (including in the current code) we <strong>don't need a variable at all</strong> in the first place, so it matters even less what the types are. playTheGame(new Player(), new BetterPlayer()) works just fine.

Answer3:

The book declared p2 as a Player only for illustrative purposes. It could be declared a BetterPlayer and the program would perform exactly the same. they wanted to show that a BetterPlayer could be assigned to a variable of type Player.

Answer4:

The key is that a BetterPlayer can be passed to playTheGame() as if it were a Player. When playTheGame() calls p2.Move(), it calls the function BetterPlayer.move(), not Player.move().

This means that you can come up with any subclass of Player and it will work fine in playTheGame() without doing any change whatsoever to playTheGame(). This means that you can create whatever Player subclass you like, with whatever .move() behavior you like, and playTheGame() will work fine with it.

For one thing, you are having old code call new code without any change in the old code, and this can be important.

For another, you're providing a way to plug in anything that's a Player to some pre-existing code, and therefore providing an abstraction barrier. playTheGame() not only doesn't have to know anything about Player, it doesn't have to insist on it being called with a Player.

Answer5:

Subclasses have an IS-A relationship to superclasses. BetterPlayer IS-A Player.

For your first question about 'upcasting' your wording is flawed. You can pass p2 into the method because it takes a Player, and BetterPlayer IS-A Player.

For your second question, yes.

For your third question, you are again correct. You can just define p2 as a BetterPlayer to start with though, and then you can use it anywhere you need a Player, and anywhere you need a BetterPlayer.

Answer6:

The advantage is that p1.move() and p2.move() call different functions, without playTheGame having to do something like this (in pseudocode as my Java is rusty):

if (p1 is Player) call Player.move(p1) else if (p1 is BetterPlayer) call BetterPlayer.move(p1) if (p2 is Player) call Player.move(p2) else if (p2 is BetterPlayer) call BetterPlayer.move(p2)

Answer7:

That's good to make maintaining the code easier - in case you need a StupidPlayer, you just have to change

Player p2 = new BetterPlayer();

to

Player p2 = new StupidPlayer();

and it's finished. No need to modify other methods.

Answer8:

<blockquote>

What is the advantage to declaring an object of one type as in instance of another?

</blockquote>

In this example, there is no advantage.

A more practical example of polymorphism would be an array of players (Player[]) or list (List<Player>) that could contain Players, BetterPlayers, and any other Player subclass.

Answer9:

A pretty typical analogy is a system which draws shapes.

You create many different shapes and need to place them on your screen. Writing code to do this without polymorphism is tricky. If all the specific shapes (square, circle, triangle, glu-teapot, whatever) then you can put them in a single array of type Shape and then you can just say something like

foreach Shape s in ArrayOfShapes{ s.draw(); // They all implement draw so it makes our life easy. }

Answer10:

The benefit is that you are able to take advantage of all of the functions / attributes of the parent class in addition to the child class. It's a way of making your code more flexible and as you learn more about the need to create families of objects you'll begin to appreciate the added flexibility provided. For instance, suppose I have a parent class with 5 methods in it, I could create a sub-class or child and add more functionality to the class giving you access to say another 3 more specialized methods. The basic idea is that the child classes should extend the functionality of the parent class enabling you to reuse more code and keep each class shorter and more cohesive. If you want to gain an appreciation for the art of object oriented programming I recommend you take a peek at the <a href="http://en.wikipedia.org/wiki/GRASP_%28object-oriented_design%29" rel="nofollow">GRASP Patterns wiki</a>. It has sufficiently simple code examples that should help you see the value in having classes extend other classes.

Recommend

  • Cookie multiple values
  • Bit not operation in PHP(or any other language probably)
  • Symfony 3 new project error
  • How to hide the cursor in windows when dragging and dropping (possibly in python, or another languag
  • staticfiles and STATIC_URL with virrtualenv - django
  • Git: failed to read object … Invalid argument
  • Resizing ToolStripButtons to fit complete BackGround image
  • cast stl::vector containing pointers to stl::vector containing constant pointers
  • Delphi: Form becomes Frozen while assigning strings in thread
  • How to make a user wait with Laravel
  • Where in the relevant specification is it documented that some comments in a SQL script are, in fact
  • javascript variables, What does var x = a = {} do?
  • Generating anchors with PyYAML.dump()?
  • Get Currently Active User in Android
  • Alamofire and Reachability.swift not working on xCode8-beta5
  • how to solve invalid conversion specifier warning in iphone app
  • allocating memory to an array of string
  • Looking for good analogy/examples for monitor verses semaphore
  • Does Mobilefirst provide a provision to access web services directly?
  • How to match http request and response using Jersey ContainerRequestFilter and ContainerResponseFilt
  • java.lang.NoClassDefFoundError: com.parse.Parse$Configuration$Builder on below Lollipop versions
  • output of program is not same as passed argument
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Validaiting emails with Net.Mail MailAddress
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Timeout for blocking function call, i.e., how to stop waiting for user input after X seconds?
  • Why winpcap requires both .lib and .dll to run?
  • How do I rollback to a specific git commit
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Proper folder structure for lots of source files
  • Codeigniter doesn't let me update entry, because some fields must be unique
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • How do I configure my settings file to work with unit tests?
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Does armcc optimizes non-volatile variables with -O0?
  • Busy indicator not showing up in wpf window [duplicate]
  • Binding checkboxes to object values in AngularJs
  • Why do underscore prefixed variables exist?