Level of encapsulation in JAVA - java

I am working with a project and don't want to give access to the innermost classes. This is the class structure I am using,
// data types are not important unless mentioned
class One
{
protected propertyOne;
protected String id;
}
class Two
{
protected ArrayList<One> arrayOne;
protected String id;
}
class Three
{
protected ArrayList<Two> arrayTwo;
protected otherProperty;
}
Now, main class will instantiate Three and should use Two and One through member methods. If I return any of ArrayList through get function, all the data can be easily changed from anywhere. So instead of ArrayList<Two>, I am returning ArrayList<Two.id> and then another method is called with particular Two.id. This takes care of keeping ArrayLists hidden but generates lots of code and extra objects because of ArrayList<Two.id> and ArrayList<One.id>.
In C++, I would have made a const method with const return type to ensure no changes in ArrayList.
Is there any smart way in Java to keep ArrayLists hidden?

We have a similar issue with a hibernate based API. We wanted to make "accidential" change impossible, enforcing the use of services to keep the business logic in one place and enforcing some access control on the API level.
We did resolve this with proxies and a derived Readonly interface.
So if you have a property in Two, the getX method is declared in a ReadonlyTwo interface. Whenever you return a list of Two, you declare the list to be of ReadonlyTwo. The programmer can hack around this by learning the API and he will see, when the object is really Two and can be typecasted. If you want to avoid that, you would have to wrap a proxy around the real Two object, implementing the ReadonlyTwo interface.
If you now return the lists as immutable lists, your API is pretty safe from external modification, even down to the object level.
// data types are not important unless mentioned
class One implements ReadonlyOne
{
protected propertyOne;
protected String id;
}
class Two implements ReadonlyTwo
{
protected ArrayList<? extends ReadonlyOne> arrayOne;
protected String id;
}
class Three implements ReadonlyThree
{
protected ArrayList<? extends ReadonlyTwo> arrayTwo;
protected otherProperty;
}
Interfaces look like this (you did not add any getter/setter methods, so I make them up here):
interface ReadonlyThree {
List<? extends ReadonlyTwo>getArrayTwo();
}
Your application objects requires business methods to handle the modification of Two and One objects:
interface ThreeService {
ReadonlyTwo addTwo(p1, p2, p3) throws BusinessException;
void removeTwo(ReadonlyTwo twoRO) throws BusinessException;
List<? extends ReadonlyTwo>findTwoByPredicate(Predicate p) throws BusinessException;
}

Related

Is it possible to have an enum where each item is associated with a class?

I'm creating a game with hundreds of abilities, so trying to leverage abstracts and generics as much as possible.
Each ability extends an abstract Ability class with universal methods like getCooldown(player), which gets a specific ability's cooldown for a player. Inheritance saves me from having to duplicate that code in every ability class.
public abstract class Ability {
public static String getCooldown() {
int cooldown;
//logic to get cooldown in milliseconds
return cooldown;
}
}
But the logic and metadata for each ability are unique and coded like such:
public class Parry extends Ability {
public static String getDescription() {
...
}
public static void castAbility() {
...
}
}
Here's my enum. I'm using an enum because abilities and their metadata are constants that are ideally available at compile time. I also don't want to store the metadata separate from the classes which have the rest of the ability logic.
public enum AbilityEnum {
BORN_READY(BornReady.class),
JUGGLER(Juggler.class),
...
PARRY(Parry.class);
public final Class<? extends Ability> cls;
AbilityEnum(Class<? extends Ability> cls) {
this.cls = cls;
}
}
In other parts of the codebase, I want to use the Enum to generically get basic info on an ability, cast a spell, etc. I want to avoid hard-coding for any specific ability because there are 200+ of them. For example, when a player opens their skill menu, I need to grab the descriptions for every ability. I'd rather not type [ability_name].getDescription() 200+ times.
for (AbilityEnum ability : AbilityEnum.values()) {
String tooltip = ability.cls.getDescription();
...
// load descriptions into menu system so players
// can hover abilities for a tooltip description
}
If I try to run this I get the error:
Cannot resolve method 'getDescription' in 'Class'
This confuses me because I bounded the generic, so why does it think it has a Class instead of an Ability? I think I'm either misusing generics or have the wrong syntax for calling methods this way. Perhaps I should be using a list or something else instead of an enum?

Java generics for optional single value or collection

I'm trying to define a container for a whole bunch of classes as some parts of the code will make more sense with a collection but other places will make sense with single values.
Ideally I'd like to do this:
public class AllModes<T> {
private T<Car> car;
private T<Boat> boat;
private T<Train> train;
private T<Plane> plane;
...40 more of these...
}
then I'd like to use the class like:
AllModes<List> allModes;
AllModes<Optional> oneOfEachMode;
But I get the error I get is "The type T is not generic; it cannot be parameterized with arguments "
The reason I'm defining these in multiple variables and not a single HashSet based on a superclass is I want to have get methods that return the correct types to avoid consumers of this class needing to cast down everywhere as each object has its own distinct fields.
I also considered just storing a single value list or set but I thought it might less error prone to use the correct type I intended (ie. one value)
You can't achieve what you want using the Java type system.
Since you can't have a generic container type, you'll need to enforce the invariants with dedicated constructors (or subclasses).
But if you do so, the clients of your class will not be able to distinguish between different container types (Optional vs List), they will need to work with a generic abstraction (like Stream, Iterator, Iterable, whatever suits you).
Here's an example:
public class AllModes {
private final Supplier<Stream<Car>> cars;
private final Supplier<Stream<Boat>> boats;
public AllModes(Optional<Car> car, Optional<Boat> boat) {
// Assuming Java 8, when Optional did not have a stream() method yet
this.cars = () -> car.map(Stream::of).orElse(Stream.empty());
this.boats = () -> boat.map(Stream::of).orElse(Stream.empty());
}
public AllModes(List<Car> cars, List<Boat> boats) {
this.cars = cars::stream;
this.boats = boats::stream;
}
public Stream<Car> getCars() {
return cars.get();
}
public Stream<Boat> getBoats() {
return boats.get();
}
}
You can't solve it this way. Use the instanceof operator instead. Here is an example:
public class AllModes<T> {
private T object;
private void check(T object) {
if(object instanceof Boat){
System.out.println("Boat");
// your code for Boat goes here
} else if (object instanceof Car) {
System.out.println("Car");
// your code for Car goes here
}
}
}
I'd suggest you take a step back and re-consider what exactly you want to achieve with this container. E.g. ask yourself what its domain is or what the client is supposed to do with Allmodes<T>...
Another more concrete question that comes to mind is how exactly you intend to popuplate that Optional<T> generically? Will it be the first element in the List<T> or the last? Or an element which satisfies a specific Predicate<T>?
Your design doesn't seem to be that well thought out yet.
What you could do which would come close to what you descibed (in case I got that right) is provide an accessor of type Stream<T> as you could get both a List<T> aswell as an Optional<T> from it. Your client would then have to make that decision and also determine how exactly to derive the Optional<T> from the Stream<T>.
From The Java™ Tutorials - Why Use Generics?:
By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
You can have multiple types in class and then you can associated them with the fields. But in your case, you have several fields with some type. A class don't have much dependencies on others. You should design you class in a way that there are no much dependencies there.
public class AllModes<T,T1,T2,T3> {
private T car;
private T1 boat;
private T2 train;
private T3 plane;
}

Java generics in List return type on a method inherited from multiple interfaces

I'm currently working at a company that has a diverse set of modules. In that company if you want to provide module internals you provide it via a java interface, that hides the actual implementing type and gives an interface for the requesting module. Now I want to have one provider to be able to provide data for multiple modules that expose different fields or methods of the actual internal data.
Therefore I have an internal Object, which has some data and I have an interface for each module that needs access to some but not strictly all fields. Finally I have an external object that implements all those interfaces and holds an instance of the internal object to delegate the method calls:
public class InternalObject {
public int getA() { return 0; }
public int getB() { return 0; }
}
public interface ModuleXObject {
int getA();
}
public interface ModuleYObject {
int getA();
int getB();
}
public class ExternalObject implements ModuleXObject, ModuleYObject {
private InternalObject _internal;
public int getA() { return _internal.getA(); }
public int getB() { return _internal.getB(); }
}
Now that is all fine and dandy, but if I want to provide - lets say - repository methods for finding a list of said objects typed for the correct module, I run into problems with how I can achieve that. I would wish for something like the following:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This doesn't compile saying the return type is incompatible.
So my question is, if it is possible to achieve something like that and if, how?
I should note that I tried some different approaches which I want to include for completeness and to portray their downsides (in my eyes).
Approach 1:
public interface ModuleXObjectRepository {
List<? extends ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<? extends ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List<ExternalObject> loadAllObjects() {
// ...
}
}
This approach is quite close to the solution I would prefer, but results in code like this:
List<? extends ModuleXObject> objects = repository.loadAllObjects();
Therefore requiring the user to include the "? extends" into each List-Declaration regarding to an invocation of loadAllObjects().
Approach 2:
public interface ModuleXObjectRepository {
List<ModuleXObject> loadAllObjects();
}
public interface ModuleYObjectRepository {
List<ModuleYObject> loadAllObjects();
}
public class ExternalObjectRepository implements ModuleXObjectRepository, ModuleYObjectRepository {
public List loadAllObjects() {
// ...
}
}
This approach just omits the generic in the ExternalObjectRepository and therefore reduces the type safety too much in my opinion. Also I haven't tested if this actually works.
Just to reharse, is there any possible way to define the loadAllObjects-method in a way that enables users to get lists that are typed with the objects for their respective module without
requiring "? extends" in the users code
degrading type safety in the repository implementation
using class/interface level generics
The challenge with allowing it to be typed as List<ModuleXObject> is that other code may hold is as a List<ExternalObject>.
All ExternalObject instances are ModuleXObject instances but the inverse is not true.
Consider the following additional class:
public class MonkeyWrench implements ModuleXObject{
//STUFF
}
MonkeyWrench instances are NOT ExternalObject instances but if one could cast a List<ExternalObject> to a List<ModuleXObject> one could add MonkeyWrench instances to this collection, and this causes a risk of run time class cast exceptions and ruins type safety.
Other code could very easily have:
for(ExternalObject externalObject:externalObjectRepository.loadAllObjects())
If one of those instances is a MonkeyWrench instance, run time class cast, which is what generics are meant to avoid.
The implication of ? extends ModuleXObject is that you can read any object from the collection as a ModuleXObject but you can't add anything to the collection as other code may have additional constraints on the collection that are not obvious/available at compile time.
I'd suggest in your case to use ? extends ModuleXObject as its semantics seem to align with what you want, namely pulling out ModuleXObject instances, e.g.
ModuleXObjectRepository repo = //get repo however
for(ModuleXObject obj : repo.loadAllObjects()){
//do stuff with obj
}

Code repetition vs readablility

I have multiple services (in Spring MVC) that are children of a global Service. So I need to know about the best practice (or your opinions) with multiple methods with this example:
//Domain classes
public class MyParentObject{}
public class MyObj extends MyParentObject{}
//Services
public class MyParentObjectServiceImpl implements MyParentObjectService{
#Override
public MyParentObject findObjectByProp(String prop, String objectType){
//myCode (not abstract class)
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl implements MyObjectService{
private myObjType = "MyObj";
#Override
public MyObj findMyObjByProp(String prop){
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
And in this approach, I use calls like this:
MyObj foo = myObjService.findMyObjByProp(prop);
So I need to know if this approach is "better" or more apropiate that calling directly the parent method with the second parameter. E.g:
MyObj foo = (MyObj)myParentObjectService.findObjectByProp(prop, "MyObj");
..and avoiding the creation of second methods, more specific. It is important to know that the children services will be created anyway, because we have lot of code that is specific of a domain objects.
I have the idea that the first approach is better, because is more readable, but I need to support that decision with some documents, blog, or opinions to discuss this designs with my colleagues.
This looks like a tagged class hierarchy. It's difficult to comment on the value of this design in general without knowing the details. However, a slightly different approach that I would recommend is to generify your base class to gain a little bit of type safety.
In particular:
public /* abstract */ class MyParentObjectServiceImpl<T extends MyParentObject>
implements MyParentObjectService{
MyParentObjectServiceImpl(Class<T> type) { this.type = type; }
private final Class<T> type; // subclasses provide this
#Override
public T findObjectByProp(String prop){
//you can use type for object specific stuff
}
}
public class MyObjServiceImpl extends MyParentObjectServiceImpl<MyObj>
// You might not need this interface anymore
// if the only method defined is findMyObjByProp
/* implements MyObjectService */ {
MyObjServiceImpl() {
super(MyObj.class);
}
#Override
public /* final */ MyObj findMyObjByProp(String prop) {
return (MyObj) super.findObjectByProp(prop, this.myObjType);
}
}
You definitely gain in type safety (casting will only appear in the base class), you get rid of the "tags" (the strings that identify the different objects) and possibly reduce the number of classes/interfaces required to implement the whole hierarchy. I successfully used this approach several times. Note that this works best if the base class is abstract. Food for thoughts.

how to pass different enum types to a method?

I have a method which takes an enum and uses it in some fashion. The issue is that I have many different enum types and am not what acceptable practice is to pass an enum to a method.
I'm assuming that you mean you have a bunch of different enum classes that mean separate things, and that you want to pass them into one method.
To do that, use a marker interface:
public interface SpecialEnumType {
}
then:
public enum MySpecialEnumType implements SpecialEnumType {
...
}
public enum AnotherSpecialEnumType implements SpecialEnumType {
...
}
Now your method will accept a parameter of type SpecialEnumType:
public doSomething(SpecialEnumType specialEnumType) {
...
}
Having done that, you can do:
obj.doSomething(MySpecialEnumType.SomeThing);
obj.doSomething(AnotherSpecialEnumType.SomethingElse);
In general, it's perfectly alright to use an enum as a parameter type for a method argument.
UPDATE
I've used this pattern while integrating with third-party API's. For example, a little while ago I had to integrate with different shipping providers. To do this, I provided a general interface that allowed the developer to send in shipping information (like the addresses, packages, weights, packing options, etc.). If you wanted to implement integration with a new provided, all you needed to do was implement the interface.
Now each shipping provider had its own set of options. Before using marker interfaces, I had a single enum which contained all the options (of all the different shipping providers). This is obviously hard to maintain. But I couldn't split the enums into different classes because the interface specified a specific type of enum for the method arguments.
Using a marker interface, I was able to get around this problem. I created an interface called ShippingProviderOption. Then for each provider, I extended the interface and created an enum, with the specific options for that provider. This way I was able to separate out the options, but still present a common interface.
As far as code is concerned (greatly simplified and somewhat contrived, for demonstration purposes):
public interface ShippingProviderOption {
}
public enum UPSOption implements ShippingProviderOption {
...
}
public enum FedexOption implements ShippingProviderOption {
...
}
public interface ShippingProvider {
public ShippingResponse ship(ShippingProviderOption option);
}
public class UPSProvider implements ShippingProvider {
#Override
public ShippingResponse ship(ShippingProviderOption option) {
if(option == UPSOption.PackageType) {
...
}
}
}
public class FedexProvider implements ShippingProvider {
#Override
public ShippingResponse ship(ShippingProviderOption option) {
if(option == FedexOption.PickupType) {
...
}
}
}
Now in my actual implementation, I have a few methods in the marker interface. So it doesn't really even have to be a marker interface; it can contain methods.

Categories