Related
I am just now learning about Abstract classes in Java and I was wondering.
Would having package private fields be considered bad practices?
For example:
abstract class Parent {
String testField;
public void method() {
System.out.println(testField);
}
}
Then on the children class I would do
public final class Children extends Parent {
#Override
public void method() {
logger.log(testField);
}
}
In this example would it be bad practice?
Or should I make them private and instead use getters and setters for them like normally?
It depends on what you want to do. However, in many cases encapsulation or information hiding can be a useful principle. In your case, this would mean making the member variable protected or private and exposing it only through getters/setters or not at all. This yield some advantages:
You can change the implementation of your class (e.g. changing the type of testField) without breaking the code of other programmers
The code is more clear to other programmers as they only need to consider the public methods
It makes the code easier to test
It discourages feature envy and tight coupling
There's lots of advice. Prefer composition to inheritance. Prefer interfaces to base classes. Keep type hierarchies flat. Class should tend be either leaf (could be marked final) or abstract.
The most important practice here is avoiding protected. It's a mistake in the language. Also avoid default/package private access on anything but top level types.
In general (meaning exceptions are allowed under well defined circumstances), a field of a class should be private, and any access to it will require the use of a getter or a setter (or, more general, an 'accessor' or a 'mutator').
One (well known) exception is for static final fields of an immutable or primitive type – sometimes referred to as a constant.
When you can make sure (really sure) that your code is the only one that will access that field (for now and all overseeable future), you may consider to make it public (rarely), package private or protected. You will find this pattern quite often in classes from the java and javax packages; it works there because you cannot place your new classes to one of these packages, and therefore the code in your class cannot access the package private and protected fields – and because the (abstract) base classes in these packages that have protected fields are itself not public, inheritance would not help.
It will not work in most other cases (although things are changing since Jigsaw …), so you are limited to private internal classes in these cases.
Of course, when you write only disposable code, considerations like these are obsolete. Otherwise, you should always completely encapsulate all data, so that you/your code has complete control over any access/modification of it.
We can make methods protected in base abstract classes so that only sub classes override it.
protected void method() {
System.out.println(testField);
}
Okay I know this question has been asked a few times, but I need an advice on my specific case. There are Encodable's and Decodable's, and a Message is both an Encodable and a Decodable:
interface Encodable { void encode(); }
interface Decodable { void decode(); }
class Message implements Encodable, Decodable { ... }
void processEncodable(Encodable encodable) {
...
encodable.encode();
...
}
There are other Encodable's (and Decodable's) besides Message and they need to be processed in processEncodable. So far so good, but the problem is that I want to hide encode() and decode() from outside the package, and Java interface doesn't allow protected/private methods. One might suggest abstract classes, but as you can see Message should inherit both Encodable and Decodable, so that's not the case. Any suggestions?
These days I'm very much into Scala, and Scala traits allow protected/private methods and that's more intuitive IMHO. I've gone through a few answers mentioning Java interface's design philosophy, but I don't really understand why it shouldn't permit protected methods if interface was introduced as an alternative to multiple inheritance, while abstract classes do..
Being an alternative doesn't imply that it is a full substitute. Interfaces are Service Contracts and so they expose the functionalities that a certain class provides to its clients, being a client anyone with access to the interface.
If you want to hide encode and decode from outside the package (that means that your logic should also stay in the package with the Message class) don't expose them through the interface and, instead, allow them to be protected (or package private) methods of your Message class (or a superclass, if various classes will be encodable/decodable).
This is not an isolated rule. There are mechanisms to achieve what you want without breaking the concept of an Interface. Just think about this: What good does that method to the interface if you can access it only inside a package? What's the point of having such methods in an interface if they can be class methods that are, also, available to the members of the package with the proper modifiers?
I was asked a question, I wanted to get my answer reviewed here.
Q: In which scenario it is more appropriate to extend an abstract class rather than implementing the interface(s)?
A: If we are using template method design pattern.
Am I correct ?
I am sorry if I was not able to state the question clearly.
I know the basic difference between abstract class and interface.
1) use abstract class when the requirement is such that we need to implement the same functionality in every subclass for a specific operation (implement the method) and different functionality for some other operations (only method signatures)
2) use interface if you need to put the signature to be same (and implementation different) so that you can comply with interface implementation
3) we can extend max of one abstract class, but can implement more than one interface
Reiterating the question: Are there any other scenarios, besides those mentioned above, where specifically we require to use abstract class (one is see is template method design pattern is conceptually based on this only)?
Interface vs. Abstract class
Choosing between these two really depends on what you want to do, but luckily for us, Erich Gamma can help us a bit.
As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later. – Erich Gamma
You can’t go and change an Interface without having to change a lot of other things in your code, so the only way to avoid this would be to create a whole new Interface, which might not always be a good thing.
Abstract classes should primarily be used for objects that are closely related. Interfaces are better at providing common functionality for unrelated classes.
When To Use Interfaces
An interface allows somebody to start from scratch to implement your interface or implement your interface in some other code whose original or primary purpose was quite different from your interface. To them, your interface is only incidental, something that have to add on to the their code to be able to use your package. The disadvantage is every method in the interface must be public. You might not want to expose everything.
When To Use Abstract classes
An abstract class, in contrast, provides more structure. It usually defines some default implementations and provides some tools useful for a full implementation. The catch is, code using it must use your class as the base. That may be highly inconvenient if the other programmers wanting to use your package have already developed their own class hierarchy independently. In Java, a class can inherit from only one base class.
When to Use Both
You can offer the best of both worlds, an interface and an abstract class. Implementors can ignore your abstract class if they choose. The only drawback of doing that is calling methods via their interface name is slightly slower than calling them via their abstract class name.
reiterating the question: there is any other scenario besides these
mentioned above where specifically we require to use abstract class
(one is see is template method design pattern is conceptually based on
this only)
Yes, if you use JAXB. It does not like interfaces. You should either use abstract classes or work around this limitation with generics.
From a personal blog post:
Interface:
A class can implement multiple interfaces
An interface cannot provide any code at all
An interface can only define public static final constants
An interface cannot define instance variables
Adding a new method has ripple effects on implementing classes (design maintenance)
JAXB cannot deal with interfaces
An interface cannot extends or implement an abstract class
All interface methods are public
In general, interfaces should be used to define contracts (what is to be achieved, not how to achieve it).
Abstract Class:
A class can extend at most one abstract class
An abstract class can contain code
An abstract class can define both static and instance constants (final)
An abstract class can define instance variables
Modification of existing abstract class code has ripple effects on extending classes (implementation maintenance)
Adding a new method to an abstract class has no ripple effect on extending classes
An abstract class can implement an interface
Abstract classes can implement private and protected methods
Abstract classes should be used for (partial) implementation. They can be a mean to restrain the way API contracts should be implemented.
Interface is used when you have scenario that all classes has same structure but totally have different functionality.
Abstract class is used when you have scenario that all classes has same structure but some same and some different functionality.
Take a look the article : http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html
There are a lot of great answers here, but I often find using BOTH interfaces and abstract classes is the best route. Consider this contrived example:
You're a software developer at an investment bank, and need to build a system that places orders into a market. Your interface captures the most general idea of what a trading system does,
1) Trading system places orders
2) Trading system receives acknowledgements
and can be captured in an interface, ITradeSystem
public interface ITradeSystem{
public void placeOrder(IOrder order);
public void ackOrder(IOrder order);
}
Now engineers working at the sales desk and along other business lines can start to interface with your system to add order placement functionality to their existing apps. And you haven't even started building yet! This is the power of interfaces.
So you go ahead and build the system for stock traders; they've heard that your system has a feature to find cheap stocks and are very eager to try it out! You capture this behavior in a method called findGoodDeals(), but also realize there's a lot of messy stuff that's involved in connecting to the markets. For example, you have to open a SocketChannel,
public class StockTradeSystem implements ITradeSystem{
#Override
public void placeOrder(IOrder order);
getMarket().place(order);
#Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
The concrete implementations are going to have lots of these messy methods like connectToMarket(), but findGoodDeals() is all the traders actually care about.
Now here's where abstract classes come into play. Your boss informs you that currency traders also want to use your system. And looking at currency markets, you see the plumbing is nearly identical to stock markets. In fact, connectToMarket() can be reused verbatim to connect to foreign exchange markets. However, findGoodDeals() is a much different concept in the currency arena. So before you pass off the codebase to the foreign exchange wiz kid across the ocean, you first refactor into an abstract class, leaving findGoodDeals() unimplmented
public abstract class ABCTradeSystem implements ITradeSystem{
public abstract void findGoodDeals();
#Override
public void placeOrder(IOrder order);
getMarket().place(order);
#Override
public void ackOrder(IOrder order);
System.out.println("Order received" + order);
private void connectToMarket();
SocketChannel sock = Socket.open();
sock.bind(marketAddress);
<LOTS MORE MESSY CODE>
}
Your stock trading system implements findGoodDeals() as you've already defined,
public class StockTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
deals = <apply magic wizardry>
System.out.println("The best stocks to buy are: " + deals);
}
but now the FX whiz kid can build her system by simply providing an implementation of findGoodDeals() for currencies; she doesn't have to reimplement socket connections or even the interface methods!
public class CurrencyTradeSystem extends ABCTradeSystem{
public void findGoodDeals();
ccys = <Genius stuff to find undervalued currencies>
System.out.println("The best FX spot rates are: " + ccys);
}
Programming to an interface is powerful, but similar applications often re-implement methods in nearly identical ways. Using an abstract class avoids reimplmentations, while preserving the power of the interface.
Note: one may wonder why findGreatDeals() isn't part of the interface. Remember, the interface defines the most general components of a trading system. Another engineer may develop a COMPLETELY DIFFERENT trading system, where they don't care about finding good deals. The interface guarantees that the sales desk can interface to their system as well, so it's preferable not to entangle your interface with application concepts like "great deals".
Which should you use, abstract classes or interfaces?
Consider using abstract classes if any of these statements apply to your use case:
You want to share code among several closely related classes.
You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private).
You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.
Consider using interfaces if any of these statements apply to your use case:
You expect that unrelated classes would implement your interface.
For example, the interfaces Comparable and Cloneable are implemented by many unrelated classes.
You want to specify the behavior of a particular data type, but not concerned about who implements its behavior.
You want to take advantage of multiple inheritance of type.
New methods added regularly to interface by providers, to avoid issues extend Abstract class instead of interface.
http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Things have been changed a lot in last three years with addition of new capabilities to interface with Java 8 release.
From oracle documentation page on interface:
An interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. Method bodies exist only for default methods and static methods.
As you quoted in your question, abstract class is best fit for template method pattern where you have to create skeleton. Interface cant be used here.
One more consideration to prefer abstract class over interface:
You don't have implementation in base class and only sub-classes have to define their own implementation. You need abstract class instead of interface since you want to share state with sub-classes.
Abstract class establishes "is a" relation between related classes and interface provides "has a" capability between unrelated classes.
Regarding second part of your question, which is valid for most of the programming languages including java prior to java-8 release
As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later. – Erich Gamma
You can’t go and change an Interface without having to change a lot of other things in your code
If you prefer abstract class to interface earlier with above two considerations, you have to re-think now as default methods have added powerful capabilities to interfaces.
Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.
To select one of them between interface and abstract class, oracle documentation page quote that:
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods.
With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.
Refer to these related questions fore more details:
Interface vs Abstract Class (general OO)
How should I have explained the difference between an Interface and an Abstract class?
In summary : The balance is tilting more towards interfaces now.
Are there any other scenarios, besides those mentioned above, where specifically we require to use abstract class (one is see is template method design pattern is conceptually based on this only)?
Some design patterns use abstract classes (over interfaces) apart from Template method pattern.
Creational patterns:
Abstract_factory_pattern
Structural patterns:
Decorator_pattern
Behavioral patterns:
Mediator_pattern
You are not correct. There are many scenarios. It just isn't possible to reduce it to a single 8-word rule.
The shortest answer is, extend abstract class when some of the functionalities uou seek are already implemented in it.
If you implement the interface you have to implement all the method. But for abstract class number of methods you need to implement might be fewer.
In template design pattern there must be a behavior defined. This behavior depends on other methods which are abstract. By making sub class and defining those methods you actually define the main behavior. The underlying behavior can not be in a interface as interface does not define anything, it just declares. So a template design pattern always comes with an abstract class. If you want to keep the flow of the behavior intact you must extend the abstract class but don't override the main behavior.
In my opinion, the basic difference is that an interface can't contain non-abstract methods while an abstract class can.
So if subclasses share a common behavior, this behavior can be implemented in the superclass and thus inherited in the subclasses
Also, I quoted the following from "software architecture design patterns in java" book
" In the Java programming language, there is no support for multiple inheritance.
That means a class can inherit only from one single class. Hence inheritance
should be used only when it is absolutely necessary. Whenever possible, methods
denoting the common behavior should be declared in the form of a Java interface to be implemented by different implementer classes. But interfaces suffer from the limitation that they cannot provide method implementations. This means that every implementer of an interface must explicitly implement all methods declared in an interface, even when some of these methods represent the invariable part of the functionality and have exactly the same implementation in all of the implementer classes. This leads to redundant code. The following example demonstrates how the Abstract Parent Class pattern can be used in such cases without requiring redundant method implementations."
Abstract classes are different from interfaces in two important aspects
they provide default implementation for chosen methods (that is covered by your answer)
abstract classes can have state (instance variables) - so this is one more situation you want to use them in place of interfaces
This is a good question The two of these are not similar but can be use for some of the same reason, like a rewrite. When creating it is best to use Interface. When it comes down to class, it is good for debugging.
This is my understanding, hope this helps
Abstract classes:
Can have member variables that are inherited (can’t be done in interfaces)
Can have constructors (interfaces can’t)
Its methods can have any visibility (ie: private, protected, etc - whereas all interface methods are public)
Can have defined methods (methods with an implementation)
Interfaces:
Can have variables, but they are all public static final variables
constant values that never change with a static scope
non static variables require an instance, and you can’t instantiate an interface
All methods are abstract (no code in abstract methods)
all code has to be actually written in the class that implements the particular interface
Usage of abstract and interface:
One has "Is-A-Relationship" and another one has "Has-A-Relationship"
The default properties has set in abstract and extra properties can be expressed through interface.
Example: --> In the human beings we have some default properties that are eating, sleeping etc. but if anyone has any other curricular activities like swimming, playing etc those could be expressed by Interface.
Abstract classes should be extended when you want to some common behavior to get extended. The Abstract super class will have the common behavior and will define abstract method/specific behavior which sub classes should implement.
Interfaces allows you to change the implementation anytime allowing the interface to be intact.
I think the answers here are missing the main point:
Java interfaces (the question is about Java but there are similar mechanisms in other languages) is a way to partially support multiple inheritance, i.e. method-only inheritance.
It is similar to PHP's traits or Python's duck typing.
Besides that, there is nothing additional that you truly need an interface for --and you cannot instantiate a Java interface.
Which pattern can be used, or what is the way, if I have some classes where some of the interface are protected, but I want to use it outside the package and out of the hierarchy?
I don't want to change the access modifier of those old (legacy) classes.
The following code shows how to access such a field:
Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
The same thing could be done in a method as well. But as a pattern, you better pack it in a static utility method such as ReflectionAccessor.accessField(Class class, Object object, String fieldName).
If the part of the classes that you need access to is protected, you can access it via inheritance.
You may also be able to access the protected parts via those classes that do have access to the protected code.
A design pattern that can probably be used is Proxy.
In this case, the Proxy could inherit from the class you're interested in, and make the methods you're interested in available locally.
Before all this, however, consider carefully why these parts of the interface did not have public scope. There may have been good reasons not to expose them.
You can use a class Adapter. The Class adapter will derive from the Legacy classes and expose public interface methods which will internally call your protected methods. Your client will call the public methods of the class adapter which will internally call your legacy classes.
The whole point of a protected method is to make it inaccessible from the outside, and making methods protected is often some important point of a design pattern.
You want to break the encapsulation of the classes, and there is no design pattern that will help you do that. Only dirty reflection calls.
Faster than reflection, but equally dirty (or possibly more so): define a class in the same package as the legacy classes. Give it all the public methods you want. Have these public methods delegate to protected methods of the legacy classes.
I think I need to wash my hands after typing that.
Why are all methods in an interface definition implicitly public? Why does it not allow a protected method?
Because an interface is supposed to mean "what you can see from outside the class". It would not make sense to add non-public methods.
Although the often quoted reason is that "interfaces define public APIs", I think that is an over-simplification. (And it "smells" of circular logic too.)
It would not be meaningless to have interfaces that have a mixture of access modifiers; e.g. partly public and partly restricted to other classes in the same package as the interface. In fact, in some cases this could be down-right useful, IMO.
Actually, I think that the part of reasoning behind making members of an interface implicitly public is that it makes the Java language simpler:
Implicitly public interface members are simpler for programmers to deal with. How many times have you seen code (classes) where the method access modifiers were chosen seemingly at random? A lot of "ordinary" programmers have difficulty understanding how best to manage Java abstraction boundaries1. Adding public/protected/package-private to interfaces makes it even harder for them.
Implicitly public interface members simplify the language specification ... and hence the task for Java compiler writers, and the folks who implement the Reflection APIs.
The line of thinking that the "interfaces define public APIs" is arguably a consequence (or characteristic) of the simplifying language design decision ... not the other way around. But in reality, the two lines of thought probably developed in parallel in the minds of the Java designers.
At any rate, the official response to the RFE in JDK-8179193 makes it clear that the Java design team decided2 that allowing protected on interfaces adds complexity for little real benefit. Kudos to #skomisa for finding the evidence.
The evidence in the RFE settles the issue. That is the official reason why that has not been added.
1 - Of course, top-gun programmers have no difficulty with these things, and may welcome a richer palette of access control features. But, what happens when their code is handed over to someone else to maintain?
2 - You may disagree with their decision or their stated reasoning but that is moot.
I have to say that this question has been re-opened by the introduction of default methods in Java 8. The project that I am working on right now is, similar to the base nature of an interface, meant to abstract intention from implementation.
There are several cases in which I could drastically simplify my code with a "default protected" method. It turns out that that doesn't actually work, as interfaces still stick to Java 7 logic. A normal protected method doesn't especially make any sense, for the reasons mentioned above; but if a default public method requires a low-level resource that will not likely change and can be provided by a protected method, it seems to me that having "default protected" work would not only maintain cleaner code, it would protect future users from accidental abuses.
(This tragically does not change the fact that I still need to over-complicate my code with otherwise unnecessary abstracts; but I do intend to put a feature request in at Oracle.)
Several answers here employ circular reasoning to explain why interface methods can't be protected: it's because they have to be public, so obviously they can't be protected!
That explains nothing, but fortunately someone raised an enhancement request for protected methods in interfaces as a JDK bug a couple of years ago, which sheds some light on the issue:
Protected methods in interfaces: share across packages
Since modifiers are a bit limited in Java, a way to share methods
across packages is restricted to public methods. Sometimes it is
dangerous to make a method public, but it needs to be because of the
lack of proper modifiers. My solution overcomes this limitation.
The java language specification doesn't currently allow the protected
modifier for interface methods. We can take advantage of this fact and
use protected for interface methods for this new feature.
If an interface method is marked protected and the interface is
implemented by a class in another package, the method would not need
to be public, but could also be private or at least package protected.
The method is visible, what ever the class declares it to be and
additionally visible in the source package of the interface (and sub
packages?).
This way we could share certain methods across well known packages.
And this is the response to that enhancement request, which was closed with status Won't fix:
This proposal attempts to solve a problem in a way that adds
complexity and special cases for little actual gain. A typical way to
solve this problem is to have a private class that implements a public
interface. The implementation methods are public, but are within a
private class, so they remain private.
An alternative available starting in Java 9 is to make classes and
methods public, but within a module that has a qualified-export to
specific "friend" modules instead of being exported to the general
public.
So the authoritative takeaways from that bug report are:
The current situation is not going to change; interfaces are unlikely to ever support protected methods.
The justification for not supporting protected methods in interfaces is that it "adds complexity and special cases for little actual gain".
Since Java 9 there is an alternative approach for providing package level access to methods. Use the Java Platform Module System (JPMS) to "make classes and methods public, but within a module that has a qualified-export to specific "friend" modules instead of being exported to the general public".
Because interfaces define public APIs. Anything that's protected is an internal detail which does not belong in an interface.
You can use abstract classes with protected abstract methods, but interfaces are restricted to public methods and public static final fields.
I strongly feel that interfaces should allow protected methods; who said that interfaces have to be visible to everyone in the whole world? As to your point that it might confuse "ordinary" (read:incompetent) programmers: So much of OOP is about properly structuring objects, classes, packages etc., if a programmer has a hard time with doing all that properly, he has a much bigger problem. Java was built for that type of thing.
Perhaps, because it is an interface, i.e. it is there to tell clients what they can do with instances, rather than to tell them what they can not do.
Since an implementing class must implements ALL the methods declared in your interface, what would happen if your implementing class was in a different package ?
Declaring internal subinterfaces is a good practice, but you can not declare your internal methods as protected in an interface in Java, technically.
Of course, you can create another interface for internal use which extends the public interface:
package yourpackage;
public interface PublicInterface {
public void doThing1();
public void doThing2();
public void doThing3();
}
package yourpackage;
interface InternalInterface extends PublicInterface {
void doAnyInternalThing1();
void doAnyInternalThing2();
}
You may use the InternalInterface interface inside the package, but you should accept any subtype of PublicInterface (in public methods):
package yourpackage;
public class SomeClass {
public void someMethod(PublicInterface param) {
if (param instanceof InternalInterface) {
// run the optimized code
} else {
// run the general code
}
}
}
Outside the package users can use PublicInterface without problems.
Usually programmers create abstract classes in similar situations. However, in this case we lose the benefits of multiple inheritance.
Interface If you want to use something like you described go on with abstract classes or nested interfaces.
An exerpt from the Code Style about interface variables, but still apply to methods though:
Interface variables are implicitly public because interfaces are intended to provide an Application Programming Interface (API) that is fully accessible to Java programmers to reference and implement in their own applications. Since an interface may be used in Java packages that are different from their own, public visibility ensures that program code can access the variable.
The only scenario where it would make sense is when you want to restrict visibility to the same package. All the other uses of protected are not applicable. Specifically, protected methods are often used to provide access to some details of lower level implementations for descendants. But declaring that in an interface doesn't make sense, as there's no lower level implementation to expose.
And even the package scenario is not really what interfaces are about.
To achieve what you probably want, you need two interfaces, one for internal use and one that you expose in the public API. (With the internal one possibly, but not necessarily extending the public one.) Or, as others pointed out, an abstract superclass.
Non-public members are generally used by public members. For example, AbstractList.removeRange(int, int) is used by AbstractList.clear(), and overriding it will improve the performance of clear.
If protected methods are allowed in interfaces, it means that most public default implementations will rely on these methods. If a subclass does not need default implementations and override all public methods, then all non-public methods will no longer be useful. And if they are abstract, we will still have to override them, which makes subclasses complicated.
Protected methods are always accessible by sub-class only if subclass extends the base class.
In case of interface, subclass never extends the interface. It implements the interface.
Protected methods are accessible via extend and not with implement.
Interfaces are meant to expose methods to the outer world. Thus these methods are public by nature. However, if you want to introduce abstraction within the same family of classes it is possible by creating another level of abstraction between your interface and implementation class, i.e. an abstract class. An example is demonstrated below.
public interface MyInterface {
public void publicMethod(); // needs to be public
}
public abstract class MyAbstractClass implements MyInterface {
#Override
public void publicMethod() {
protectedMethod(); // you can call protected method here
// do other stuff
}
protected abstract void protectedMethod(); // can be protected
}
public class MyClass extends MyAbstractClass {
#Override
protected void protectedMethod() {
// implement protected method here, without exposing it as public
}
}
I know this is very late/old and I am sure that by now you have a lot more experience than me, so if this helps anyone, cheers, ...
I've found a way that keeps things comfortably cohesive, that prevents the usage of objects when dealing with protected's in-package.
In hindsight this seems ridiculously easy, but the fact of the matter is that the goal of whatever is you want to achieve with a piece of code, becomes 10 times more difficult if you spend any amount of time to try to accommodate it to standards and/or adjusts for code reusability.
The reality is that the order, will unfold as you go..
But I made a chart cause it has helped me in something that, depending on the problem can easily mind-bend me.
public interface CommonPublics {
void publicInAll();
}
public static abstract class CommonProtecteds implements CommonPublics {
protected abstract void protectedInAll();
}
public interface MyObjectPublics {
void myObjectPublic();
}
public static class MyObject extends CommonProtecteds implements MyObjectPublics {
#Override
public void publicInAll() {
}
#Override
protected void protectedInAll() {
}
#Override
public void myObjectPublic() {
}
}
Now when you need to deal with protecteds within the same package, instead of dealing with MyObject, you can deal with CommonProtecteds instead.
Now you could in theory bring whatever logic that handles protected's inside the abstract and that's up to you, but if for whatever reason you are dealing with concurrency, is better to keep everything as tight and as close to the synchronized body as possible. so whatever the protected is required to deal with that may be required inside different locked locations is better placed in the object that will handle it.