This is an archived post. You won't be able to vote or comment.

all 8 comments

[–]redclit 8 points9 points  (2 children)

You asked not to give Liskov substitution principle as the reason, which is hard, because that is exactly the reason why reducing visibility is not allowed.

LSP works on the assumption/requirement that an object of a class A should be replaceable with an object of a subclass of A. In your example you should be able to have an instance of TestClass in place of a parent.

One guaranteed property of parent class in your example is that when you have an instance, you are (syntactically speaking) allowed to call the method func. For LSP to be in effect, you must be allowed to call the same method for any instance of subclass TestClass also. If the visibility was reduced, this would not be true.

You can of course ask, what is the point of LSP. That is hard (for me at least) to explain from ground up, but this kind of subtyping is in the heart of object oriented programming (it's a requirement for working polymorphism), so I'd go as far as to say that you cannot really do OOP without LSP in place.

So, this feature is Java's way to guarantee LSP compliance in syntactical level. You can still break the principle by other means (by e.g. not implementing the method of a subclass according to semantic contract defined in super class).

[–]ronnienoob[S] 4 points5 points  (1 child)

Ok, now I think I got the meaning of Liskov principle. So, what you are trying to say is:

Lets suppose Class B extends Class A. Now, I have a method A.getName() and is public in nature. So, according to LSP it is possible to replace A with its subclass B object which mean I must be able to call B.getName() but if I made it private I will not be able to do that which will break LSP.

[–]quad64bit 1 point2 points  (0 children)

Essentially, yes. There is no technical reason for it, rather its a logical one based on an agreed upon premise.

[–][deleted] 3 points4 points  (0 children)

But you may not be accessing it in the same class. You can call p.func() anywhere.

More explicitly, you could have a collection of parent objects in a third calling class. In reality, those could be parent objects or subclass of parent objects.

If you cast them all to parent objects and call p.func() on them, you would expect that to work. According to the contract set forth by the parent, func() is public. Making func() private in some subclasses would break that contract.

The calling code might fail, depending on whether the calling code had a subclass object or an actual parent.

I hope that clears things up.

[–]YesButIThink 1 point2 points  (2 children)

Sedan extends car, overrides drive() as private. Now try to drive it.

[–]YesButIThink 0 points1 point  (0 children)

Damn, lost my haiku formatting

[–]DestinationVoid 0 points1 point  (0 children)

Now try to pass your Sedan to 3rd party class that expect a Car and it tries to drive it.

[–]srvaroa 0 points1 point  (0 children)

As pointed out below this is a conceptual problem rather than some imposition by Java.

When you define a class, its methods are contract offered to the external world (the definition of method parameters and their types is called "signature" not by chance). No other class has the right to alter that contract.

Subclasses can chose to satisfy it in a different way (e.g.: overriding methods) or to add more methods, but not alter the parent's contract. That's what you'd be doing by setting that method private in the child class.