Why should I reference the base class when I can access all the methods just as well by referencing the subclass?

后端 未结 6 1710
后悔当初
后悔当初 2021-01-20 14:32

I am learning java concepts. I got a doubt in java inheritance concept. In inheritance we can assign subclass instance to a base class reference and with that we can access

相关标签:
6条回答
  • 2021-01-20 15:09

    Polymorphism.

    I am a method that gives you a List<String>. All you need to know about the thing I've actually given you is that it's a list and has the behaviour and semantics of a list, i.e. you can put things in it, it'll maintain their ordering, and you can iterate over it.

    What you don't need to know is how I'm storing things, how I'm making them accessible, etc. That's not important. For all you care, it could be a LinkedList<String>, an ArrayList<String> or something entirely new. Suffice it to say, I've picked something, and you can happily use it.

    You're absolutely right that when you're using inheritance to extend classes and add new behaviour, then you need to reference the subclass to be able to access it. The two approaches are somewhat complimentary, but different, use cases.

    0 讨论(0)
  • 2021-01-20 15:13

    Let us say Vehicle is the base class and Car and Plane are subclasses. Let us say Vehicle has has a method move().

    Car overrides this by going on road. Plane overrides this by flying.

    Why move() should be part of Vehicle base class?

    Because any Vehicle can move(). But we can't implement move() in Vehicle because all vehicles doesn't move the same way i.e. there is no common behavior. We still want this in the base class so that we can have polymorphic behavior i.e. we can write code like below. As you can see there is only one method called runVehicle(...) that can work on any Vehicle class.

    void runVehicle(Vehicle v)
    {
      v.move();
    }
    
    Car c=new Car();
    runVehicle(c);
    
    Plane p=new Plane();
    runPlane(p);
    
    0 讨论(0)
  • 2021-01-20 15:17

    Inheritance and Polymorphism are cornerstones of object-oriented programming and serve a few different purposes, in short:

    • Code reuse by extending a base class with specific functionality,
    • Interface design by providing an abstract set of functionality, which where different implementations are tailored to different requirements and
    • Encapsulation by hiding specific functionality, which isn't needed in certain contexts

    among others.

    The last point also highlights, why one might use a restricted set of functionality, even in a case the actual implementation provides more than that. Take for example the Collection interface. By using this interface, we focus on methods like isEmpty, contains or size but not the actual implementation.

    0 讨论(0)
  • 2021-01-20 15:22

    There is no real need to do that, except when the API demands it. For example, if in a particular API or code library there is a

    void ReallyUsefulFunction(BaseClass instance)
    

    that you would like to use, you can derive a class fom BaseClass and implement its methods in the SubClass. Then you can now pass the subclass to the function.

    Still, technically, you could implement your own

    void MyReallyUsefulFunction(MyClass instance)
    

    which imitates the same functionality. But like what MYYM had explained, the benefits of code reuse etc. can be huge, and that is when you will want to take advantage of polymorphism.

    0 讨论(0)
  • 2021-01-20 15:26

    What you've described is the essence of polymorphism. It's a word from the Greek that means "many forms".

    If I gave you a simple hierarchy like this, you can see how the test code can get different calculation implementations out of each object without concerning itself about what kind of Shape it was dealing with:

    public interface Shape
    {
        double calculateArea();
    }
    
    class Circle implements Shape
    {
        private double radius;
    
        Circle(double r) { this.radius = r; }
    
        public double calculateArea() { return Math.PI*radius*radius; }
    }
    
    class Square implements Shape
    {
        private double side;
    
        Square(double s) { this.side = s; }
    
        public double calculateArea() { return side*side; }
    }
    
    // This would be a separate JUnit or TestNG annotated test.
    public class ShapeTest
    {
        @Test
        public void testCalculateArea()
        {
            Map<Shape, Double> expected = new HashMap<Shape, Double>()
            {{
                put(new Circle(1.0), Math.PI);
                put(new Square(1.0), 1.0);            
            }};
    
    
            for (Shape shape : expected.keySet())
            {
                Assert.assertEquals(expected.get(shape), shape.calculateArea());
            }       
        }
    }
    
    0 讨论(0)
  • 2021-01-20 15:28

    The reason why you may want to do this is to create more robust designs. Take for example the Collections Framework in Java. You have a List interface and then you have two implementations, ArrayList and LinkedList.

    You can write your program to use a LinkedList specifically or an ArrayList specifically. However, your program then depends on those specific implementations.

    If you write your program to depend on the super type, List, instead then your program can work for either of the List implementations. Lets say you want to write a method that does something to a List and you wrote this:

      public void doSomething(ArrayList a){}
    

    This method can only be called with an ArrayList, not a LinkedList. Suppose that you wanted to do the same thing with a LinkedList? Do you then duplicate your code? No.

      public void doSomething(List l){}
    

    Will be able to accept either type of List.

    The principle behind this is program to an interface not an implementation. That is, List defines the functions of ALL lists.

    There are many many examples of this usage.

    0 讨论(0)
提交回复
热议问题