Say I have like 50 different classes that extends "CustomEnchantment", is there any way to have a static getter in the abstract class that gets me one of the values of a specific class. Say I want max level of "Rage" then i'd do Rage.getMaxLevel() or something, in a static way. Problem is that getting an instance would mean i'd have to make 50+ instances 1 for each enchant. I want to just have a fix way to get a specific enchant's max level. I have tried to just include a "getMaxLevel()" and it returns it fine, but with that, i would need an instance of every single class that extends the abstract class, i'd rather have a static way of getting 1 specific class value.
Some examples:
I have 3 classes extending Person. Person includes the variables age and name.
In the class Josh, his name is set to "Josh" and age 17. In the class Jeff, his name is "Jeff" and age 20. In the class Jennica, name is "Jennica" and her age is 19. What I need is a method to return the age from a specific one of these classes at any time with only 1 method. So for example (This wont work) getAge(Jennica) gets Jennica's age, getAge(Josh) returns 17 for his age etc.. I need this to be used in a static or in a way where I can access it easily.
By a static variable, you could realize that. You just have to take care that your static member is always updated by the subclasses max-level. If your code grows, that will make it unmaintainable.
A better approach could be to make an Manager-class like "CustomEchantmentManager" or something else. It could store a list of all your instances. Also, it could store an attribute like CustomEchantment enchantmentWithHighestLevel, where you store the instance with the highest level. Let your manager observe the enchantments and after a new level of one enchantment, check if it's level is higher than the actual stored enchantment's level and if yes, overwrite it's reference in the attribute. This will not change all your instances because it just references to your instance with the highest level.
Example for the manager:
public class CustomEnchantmentManager implements Observer {
private ArrayList<CustomEnchantment> enchantments;
private CustomEnchantment enchantmentWithHighestLevel = null;
public CustomEnchantmentManager() {
enchantments = new ArrayList<CustomEnchantment>();
}
#Override
public void update(Observable obs, Object o) {
if(this.enchantmentWithHighestLevel.getLevel() > ((CustomEnchantment)o).getLevel) {
//do Nothing
else {
this.enchantmentWithHighestLevel = (CustomEnchantment)o;
}
}
Example for an enchantment:
public class CustomEnchantment() extends Observable {
public int level = 0;
public CustomEnchantment() {
}
public void incrementLevel() {
this.level++;
setChanged(); //method from Observable
notifyObservers(this); //send Observers instance of this object
}
}
Related
I have the following classes
class Person {
private String name;
void getName(){...}}
class Student extends Person{
String class;
void getClass(){...}
}
class Teacher extends Person{
String experience;
void getExperience(){...}
}
This is just a simplified version of my actual schema. Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.
void calculate(Person p){...}
Now I want to access the methods of the child classes using this parent class object. I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT.
I guess I simplified too much in the above example, so here goes , this is the actual structure.
class Question {
// private attributes
:
private QuestionOption option;
// getters and setters for private attributes
:
public QuestionOption getOption(){...}
}
class QuestionOption{
....
}
class ChoiceQuestionOption extends QuestionOption{
private boolean allowMultiple;
public boolean getMultiple(){...}
}
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption().getMultiple())
{...}
}
}
The if statement says "cannot find getMultiple for QuestionOption." OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children)
NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance. The best way would be to restructure your application design so that there are NO parent to child dependencies. A parent should not ever need to know its children or their capabilities.
However.. you should be able to do it like:
void calculate(Person p) {
((Student)p).method();
}
a safe way would be:
void calculate(Person p) {
if(p instanceof Student) ((Student)p).method();
}
A parent class should not have knowledge of child classes. You can implement a method calculate() and override it in every subclass:
class Person {
String name;
void getName(){...}
void calculate();
}
and then
class Student extends Person{
String class;
void getClass(){...}
#Override
void calculate() {
// do something with a Student
}
}
and
class Teacher extends Person{
String experience;
void getExperience(){...}
#Override
void calculate() {
// do something with a Teacher
}
}
By the way. Your statement about abstract classes is confusing. You can call methods defined in an abstract class, but of course only of instances of subclasses.
In your example you can make Person abstract and the use getName() on instanced of Student and Teacher.
Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition". That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy. I submit that this is a type-safe, but often very bad, approach. You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).
I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java. They all suck, because Java sucks at variant types. So far the only JVM language that gets it right is Scala.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
The Scala creators actually wrote a paper about three of the eight ways. If I can track it down, I'll update this answer with a link.
UPDATE: found it here.
Why don't you just write an empty method in Person and override it in the children classes? And call it, when it needs to be:
void caluculate(Person p){
p.dotheCalculate();
}
This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.
I had the same situation and I found a way around with a bit of engineering as follows - -
You have to have your method in parent class without any parameter and use - -
Class<? extends Person> cl = this.getClass(); // inside parent class
Now, with 'cl' you can access all child class fields with their name and initialized values by using - -
cl.getDeclaredFields(); cl.getField("myfield"); // and many more
In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.
Another thing you might need to use is Object obj = cl.newInstance();
Let me know if still you got stucked somewhere.
class Car extends Vehicle {
protected int numberOfSeats = 1;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
public void printNumberOfSeats() {
// return this.numberOfSeats;
System.out.println(numberOfSeats);
}
}
//Parent class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
System.out.println(licensePlate);
}
public static void main(String []args) {
Vehicle c = new Vehicle();
c.setLicensePlate("LASKF12341");
//Used downcasting to call the child method from the parent class.
//Downcasting = It’s the casting from a superclass to a subclass.
Vehicle d = new Car();
((Car) d).printNumberOfSeats();
}
}
One possible solution can be
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption() instanceof ChoiceQuestionOption)
{
ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
boolean result = choiceQuestion.getMultiple();
//do something with result......
}
}
}
This question already has answers here:
Implementing two interfaces with two default methods of the same signature in Java 8
(7 answers)
Closed 2 years ago.
Java 8's default methods in an interface can be called from the child class using InterfaceName.super.methodName . Why doesn't Java 8 allow us to use a similar syntax to call the specific class's method name? Can this resolve the Diamond Problem encountered for multiple inheritance?
class Employee {
public static void displayName() {
System.out.println("Employee!");
}
}
class Engineer extends Employee {
public static void displayName() {
System.out.println("Engineer!");
}
}
class Manager extends Employee {
public static void displayName() {
System.out.println("Manager!");
}
}
public class Resource extends Engineer,Manager {
public static void main(String args[]) {
//Insert similar code here like InterfaceName.super.methodName to call any of the above methods to handle multiple inheritance.
}
}
In Java 8, you can not extend (inherit) multiple classes all in one shot. What I mean by this is that if you write:
public class Resource extends Engineer, Manager { //This generates a compiler error.
}
However, you may inherit multiple classes into one, main class by making a chain of inheritance.
public class Master {
public void method1(){};
}
public class Child1 extends Master{
public void method2() {};
}
public class Child2 extends Child1 {
//you can access method 1 and method 2 here by simply calling
method1();
method2();
}
A way you can go about addressing your issue is to write an "EmployeeInterface" and write an "EmployeeClass". To access the methods in "EmployeeClass", you must make an object of the "EmployeeClass" in your main method. You will need to write a constructor to pass the name of the employee in. I will provide an example here:
public interface EmployeeInterface {
public void displayName();
public void setName(String name);
}
The above is an Interface. An interface contains the methods that you want to use in a class, however, you do not yet define them here. You only write the method headers. Think of this as a shopping list. Writing an item such as bread on a shopping list does not mean you will now have bread, it just marks it as an item that needs to be purchased.
Next, you will need to write a class implementing the EmployeeInterface.
public class EmployeeClass implements EmployeeInterface{
private String employeeName;
public EmployeeClass(String name) { //This is a constructor
this.employeeName = name;
}
#Override
/**
* This function will display the name of the employee.
*/
public void displayName() {
System.out.println(employeeName);
}
#Override
/**
* This function with use the given string and change the employee's name.
*/
public void setName(String name) {
this.employeeName = name;
}//end of setName method
}//end of class
Above is the class that implements the EmployeeInterface. It looks at the Interface and says that you must define what these methods do. This is like looking at your shopping list and seeing bread, and going to the store and buying it.
There is also a constructor in this class. A constructor in java is a method that is executed upon the instantiation of an instance of a class. This means that whatever code you write in the constructor, it will be run once and only once when you make an object of the class. Constructors must be spelled the same as the class, is case sensitive, and must be public. You can add as many parameters as you'd like.
We use #Override over the functions in the class because we are overriding (Changing the body) from nothing to our definition from the EmployeeInterface. Depending on your IDE/Compiler, it may work without the #Override tag, but it is highly reccomended that you do this.
In the constructor, you see we use this.employeeName = name; the "this" keyword refers to the field (variable) within the class that we write it in. In this case, it is not necessary, because the name of the variable in the class and the name of the variable being passed in are different. But in the case that variable names are the same, you can use "this.variableName" to specify the class variable.
Finally, to use these classes, you must make a main method in a separate class to execute these functions. Making the main method is like making a sandwich out of the bread that you purchased at the store.
public class Main {
public static void main(String[] args) {
EmployeeInterface manager = new EmployeeClass("Bob");
EmployeeInterface engineer = new EmployeeClass("Mary");
System.out.println("The name of the manager is: ");
manager.displayName();
System.out.println("The name of the engineer is: ");
engineer.displayName();
manager.setName("Jack");
System.out.println("The new manager's name is: ");
manager.displayName();
}//end of method Main
}//end of class Main
Above is the method that executes the methods that you defined in the EmployeeClass using the EmployeeInterface. First, you create an object of the class, of the type that is the name of the Interface.
EmployeeInterface manager = new EmployeeClass("Bob");
This is an object of the EmployeeClass, and we called it manager. We made it of type EmployeeInterface because we want to be able to use the methods we defined in the EmployeeInterface. We write "= new EmployeeClass("Bob");" afterward because we want to make a new Instance of the EmployeeClass, and pass the String "Bob" into our constructor.
Next, we display the name of the manager.
System.out.println("The name of the manager is: ");
manager.displayName();
This will display the name of the manager.
We can also change the name of the manager with our defined "setName()" function.
manager.setName("Jack");
We call the function like this and pass in the String "Jack" which will become the new name for the manager.
Upon execution of the Main method, we get this output:
Image of the output
All in all, this solution does not use inheritance of methods to print the names of different employees, but uses an EmployeeInterface, along with a definition of the Interface, EmployeeClass, to store and display the employee names. Rather than making a new class for every employee, you make a new object with the parameters containing the name of the new employee in the main method.
I hope this answered your question, and please do reply if you require any more clarifications.
Here I also include some articles about the Java concepts I talked about.
Here is a resource for Inheritance and Interfaces.
Interfaces on Oracle
Inheritance on Oracle
Constructors on Oracle
So as part of a car rental system I need to write classes to represent large and small cars, the difference between these being that they have different size tanks and consume fuel at different rates. Currently my approach is to have an interface, Car, implemented by an abstract class AbstractCar, which is extended by two concrete classes SmallCar and LargeCar. However this is my first time using interfaces and abstract classes (we are just covering them in class and this assignment is designed to assess our knowledge of them) and I'm having trouble knowing what to place in what class.
The fill method implementations are exactly the same, they just need to refer to the correct value of FUEL_CAPACITY, so it feels that I should be implementing these methods in the AbstractCar class, but then I don't know how to get them to refer to the correct FUEL_CAPACITY values. The field fuelLevel is also obviously held by all cars so it feels that I should declare it in AbstractCar, but then I cannot access it from the subclasses without removing its privacy.
Would anyone be able to help me figure out what I'm doing wrong or misunderstanding about interfaces and inheritance? One thing I've been considering is producing an enum CarType, having AbstractCar hold a CarType as a field and all implementation is done in the AbstractCar class using if statements to switch to the correct FUEL_CAPACITY value, and simply using SmallCar and LargeCar as constructors or factory classes without much or even any actual implementations.
Thanks in advance for any help I realise its a bit long winded, however I try to make sure I'm fully understanding the concepts we are learning and that I'm implementing them correctly rather than just botching together something that 'works' but might not necessarily be the correct or most elegant solution.
You can transfer the logic to the AbstractCar with the values like you pointed out. Then just set those values in the constructor of SmallCar and LargeCar. This would be one approach. Like you pointed out, you always have to have the common logic in the parent class. You want to avoid duplicate code. Then you just have to make sure you set different values in the constructor. And if you know the fix value (as you do from the given example), you can even omit giving parameters to SmallCar or LargeCar constructors and just set those fixed values in the super() call inside the constructor.
Here is the implementation of my solution.
The interface Car, where I REMOVED the getFuelMethod() method since the access level has to be protected:
public interface Car {
RegistrationNumber getRegistration();
int getFuelCapacity();
// int getFuelLevel(); this can not be implemented
// all methods in an interface are PUBLIC
// so you have to lower the access level by removing it from the interface
// HERE goes the rest of the method signatures
}
}
The abstract class AbstractCar:
public abstract class AbstractCar implements Car {
// this is the common variable
// that is why we save it in the parent class
private int fuelCapacity;
private int fuelLevel;
// we forward the value to the parent constructor with the super call
public AbstractCar(int fuelCapacity) {
this.fuelCapacity = fuelCapacity;
// I set the value to 0 for the start, but
// you can also pass the value to the super call,
// same as fuelCapacity - it is up to you
this.fuelLevel = 0;
}
// The getters and setter allow us to retrieve the values
// from the abstract class through capsulation!
// here we have the getter to be able to retrieve the value from SmallCar and LargeCar
public int getFuelCapacity() {
return.fuelCapacity;
}
public void setFuelCapacity(int fuelCapacity) {
this.fuelCapacity = fuelCapacity;
}
protected int getFuelLevel() {
return fuelLevel;
}
protected void setFuelLevel(int fuelLevel) {
this.fuelLevel = fuelLevel;
}
// HERE goes the rest of the code
}
Here is the SmallCar implementation:
public class SmallCar extends AbstractCar {
private static final int FUEL_CAPACITY = 45;
public SmallCar() {
// we set the value in the parent class
super(FUEL_CAPACITY);
}
public int drive() {
// HERE goes the logic for drive for SmallCar. Same method is needed
// in the LargeCar class, because the logic differes.
}
// HERE goes the rest of the code
}
If you just want to hide FUEL_CAPACITY from the class user but not from the further developers, you can declare it as protected in the AbstractCar and initiallize it with a proper value in the child classes. Also I would declare a getter method getCapacity() in the AbstractCar which returns this value.
If your Capacity is only one property (only data) of Car, use #Jernej K approach, but if calculating the capacity may have some logic, use this:
Best way is to use abstract methods. you put a method to abstract Integer getCapacity(); in your abstract class
public abstract class AbstractCar implements Car {
private final RegistrationNumber registration;
private boolean isRented;
AbstractCar() {
this.registration = RegistrationNumber.getInstance();
}
public RegistrationNumber getRegistration() {
return registration;
}
public boolean isRented() {
return isRented;
}
//You can use this method in other methods of AbstractCar, but is implemented in your concrete classes
public abstract Integer getCapacity();
public boolean isFull() {
if (fuelLevel == getCapacity()) {
return true;
} else return false;
}
}
and then use it in other functions. and in your concrete class, you define the body of method:
public Integer getCapacity(){
//Your logic to calculate capacity for every concrete class here
}
In the spirit of well designed OO, a certain class I am extending has marked one of its fields protected. This class has also generously provided a public setter, yet no getter.
I am extending this class with a base class that is in turn extended by several children. How can I restrict access to the protected variable from my children while still being able to manipulate it privately and set it publicly?
See example below:
public abstract class ThirdPartyClass {
protected Map propertyMap;
public void setPropertyMap(Map propertyMap){
this.propertyMap= propertyMap;
}
// Other methods that use propertyMap.
}
public abstract class MyBaseClass extends ThirdPartyClass{
// Accessor methods for entries in propertyMap.
public getFoo(){
propertyMap.get("Foo");
}
public getBar(){
propertyMap.get("Bar");
}
// etc...
}
public class OneOfManyChildren extends MyBaseClass {
// Should only access propertyMap via methods in MyBaseClass.
}
I have already found that I can revoke access by making the field private final in MyBaseClass. However that also hinders using the setter provided by the super class.
I am able to circumvent that limitation with the "cleverness" below yet it also results in maintaining two copies of the same map as well as an O(n) operation to copy over every element.
public abstract class MyBaseClass extends ThirdPartyClass{
private final Map propertyMap = new HashMap(); // Revokes access for children.
/** Sets parent & grandparent maps. */
#Override
public final void setPropertyMap(Map propertyMap){
super.setPropertyMap(propertyMap);
this.propertyMap.clear();
this.propertyMap.putAll(propertyMap);
}
}
Are there any better ways of accomplishing this?
Note: This is only one example of the real question: How to restrict access to protected fields without maintaining multiple copies?
Note: I also know that if the field were made private in the first place with a protected accessor, this would be a non-issue. Sadly I have no control over that.
Note: IS-A relatonship (inheritance) required.
Note: This could easily apply to any Collection, DTO, or complex object.
Metaphor for those misunderstanding the question:
This is akin to a grandparent having a cookie jar that they leave accessible to all family members and anyone else in their house (protected). A parent, with young children, enters the house and, for reasons of their own, wishes to prevent their children from digging into the cookie jar ad nauseam. Instead, the child should ask the parent for a chocolate chip cookie and see it magically appear; likewise for a sugar cookie or Oreo. They need never know that the cookies are all stored in the same jar or if there even is a jar (black box). This could be easily accomplished if the jar belonged to the parent, if the grandparent could be convinced to put away the cookies, or if the grandparents themselves did not need access. Short of creating and maintaining two identical jars, how can access be restricted for children yet unimpeded for the parent & grandparent?
This might not be possible for you, but if you could derive an interface from ThirdPartyClass and make ThirdPartyClass implement it ?
Then have MyBaseClass act as a decorator by implementing the interface by delegating to a private member ThirdPartyClassImpl.
I.e.
public interface ThirdParty ...
public class ThirdPartyClass implements ThirdParty
public class MyBaseClass implements ThirdParty {
private ThirdParty decorated = new ThirdPartyClass();
public class SubclassOne extends MyBaseClass....
etc
Ok, cheating mode on:
How about you overwrite de public setter and change the map implementation to a inner class of MyBaseClass. This implementation could throw a exception on all methods of map you dont want your children to access and your MyBaseClass could expose the methods they should use by using an internal method your map implementation...
Still has to solve how the ThirdPartyMethod will access those properties, but you could force your code to call a finalizationMethod on your MyBaseClass before use it... I'm just divagating here
EDIT
Like This:
public abstract class MyBaseClass extends ThirdPartyClass{
private class InnerMapImpl implements Map{
... Throw exception for all Map methods you dont want children to use
private Object internalGet(K key){
return delegate.get(key);
}
}
public void setPropertyMap(Map propertyMap){
this.propertyMap= new InnerMapImpl(propertyMap);
}
public Object getFoo(){
return ((InnerMapImpl) propertyMap).internalGet("Foo");
}
}
Sadly, there's nothing you can do. If this field is protected, it is either a conscious design decision (a bad one IMO), or a mistake. Either way, there's nothing you can do now about it, as you cannot reduce the accessibility of a field.
I have already found that I can revoke access by making the field private final in MyBaseClass.
This isn't exactly true. What you are doing is called variable hiding. Since you are using the same variable name in your subclass, references to the propertyMap variable now point to your private variable in MyBaseClass. However, you can get around this variable hiding very easily, as shown in the code below:
public class A
{
protected String value = "A";
public String getValue ()
{
return value;
}
}
public class B extends A
{
private String value = "B";
}
public class C extends B
{
public C ()
{
// super.value = "C"; --> This isn't allowed, as B.value is private; however the next line works
((A)this).value = "C";
}
}
public class TestClass
{
public static void main (String[] args)
{
A a = new A ();
B b = new B ();
C c = new C ();
System.out.println (new A ().getValue ()); // Prints "A"
System.out.println (new B ().getValue ()); // Prints "A"
System.out.println (new C ().getValue ()); // Prints "C"
}
}
So, there's no way you can "revoke" access to the protected class member in the super class ThirdPartyClass. There aren't a lot of options left to you:
If your child class do not need to know about the class hierarchy above MyBaseClass (i.e. they won't refer to ThirdPartyClass at all), and if you don't need them to be subclasses of ThirdPartyClass then you could make MyBaseClass a class which does not extend from ThirdPartyClass. Instead, MyBaseClass would hold an instance of ThirdPartyClass, and delegate all calls to this object. This way you can control which part of ThirdPartyClass's API you really expose to your subclasses.
public class MyBaseClass
{
private ThirdPartyClass myclass = new ThirdPartyClass ();
public void setPropertyMap (Map<?,?> propertyMap)
{
myclass.setPropertyMap (propertyMap);
}
}
If you need a direct access to the propertyMap member of ThirdPartyClass from MyBaseClass, then you could define a private inner class and use it to access the member:
public class MyBaseClass
{
private MyClass myclass = new MyClass ();
public void setPropertyMap (Map<?,?> propertyMap)
{
myclass.setPropertyMap (propertyMap);
}
private static class MyClass extends ThirdPartyClass
{
private Map<?,?> getPropertyMap ()
{
return propertyMap;
}
}
}
If the first solution doesn't apply to your case, then you should document exactly what subclasses of MyBaseClass can do, and what they shouldn't do, and hope they respect the contract described in your documentation.
I am able to circumvent that limitation with the "cleverness" below yet it also results in maintaining two copies of the same map as well as an O(n) operation to copy over every element.
Laf already pointed out, that this solution can easily be circumvented by casting the child classes into the third party class. But if this is ok for you and you just want to hide the protected parent map from your child classes without maintaining two copies of the map, you could try this:
public abstract class MyBaseClass extends ThirdPartyClass{
private Map privateMap;
public Object getFoo(){
return privateMap.get("Foo");
}
public Object getBar(){
return privateMap.get("Bar");
}
#Override
public final void setPropertyMap(Map propertyMap) {
super.setPropertyMap(this.privateMap =propertyMap);
}
}
Note also, that it doesn't really matter, if the parents map is protected or not. If one really wants to access this field through a child class, one could always use reflection to access the field:
public class OneOfManyChildren extends MyBaseClass {
public void clearThePrivateMap() {
Map propertyMap;
try {
Field field =ThirdPartyClass.class.getDeclaredField("privateMap");
field.setAccessible(true);
propertyMap = (Map) field.get(this);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
return;
}
propertyMap.clear();
}
}
So it actually comes down to the question, why you want the field not to be accessible by the child classes:
1) Is it just for convenience, so it is immediately clear how your api should be used? - then it is perhaps fine to simply hide the field from the sub classes.
2) Is it because of security reasons? Then you should definitely search for another solution and use a special SecurityManager that also prohibits accessing private fields through reflection...
That said there is perhaps another design you could try: Instead of extending the third party class, keep a final inner instance of this class and provide public access to the inner class like this:
public abstract class MyBaseClass {
private Map privateMap;
private final ThirdPartyClass thirdPartyClass = new ThirdPartyClass(){
public void setPropertyMap(Map propertyMap) {
super.setPropertyMap(MyBaseClass.this.privateMap = propertyMap);
};
};
public Object getFoo(){
return privateMap.get("Foo");
}
public Object getBar(){
return privateMap.get("Bar");
}
public void setPropertyMap(Map propertyMap) {
thirdPartyClass.setPropertyMap(propertyMap);
}
public final ThirdPartyClass asThirdPartyClass(){
return this.thirdPartyClass;
}
}
Then, whenever you need to access the third party library with an instance of the third party class, you do something like this:
OneOfManyChildren child;
thirdpartyLibrary.methodThatRequiresThirdPartyClass(child.asThirdPartyClass());
What about creating another protected variable called propertyMap ? That should over shadow if for your child classes. You can also implement it such that calling any method on it will cause an exception.
However, as accessor methods are defined in the base class, they will not see your second shadowed version and still set it appropriately.
How can I restrict access to the protected variable from my children while still being able to manipulate it privately and set it publicly?
So you want the public to have more rights than you do? You can't do that since they could always just call the public method... it's public.
Visibility on variables is just like visibility on methods, you are not going to be able to reduce that visibility. Remember that protected variables are visible outside the direct subclass. It can be accessed from the parent by other members of the package See this Answer for Details
The ideal solution would be to mess with the parent level class. You have mentioned that making the object private is a non-starter, but if you have access to the class but just cannot downscope (perhaps due to existing dependencies), you can jiggle your class structure by abstracting out a common interface with the methods, and having both the ThirdPartyClass and your BaseClass use this interface. Or you can have your grandparent class have two maps, inner and outer, which point to the same map but the grandparent always uses the inner. This will allow the parent to override the outer without breaking the grandparent.
However, given that you call it a 3rd party class, I will assume you have no access at all to the base class.
If you are willing to break some functionality on the master interface, you can get around this with runtime exceptions (mentioned above). Basically, you can override the public variable to throw errors when they do something you do not like. This answer is mentioned above, but I would do it at the variable (Map) level instead of your interface level.
If you want to allow READ ONLY access top the map:
protected Map innerPropertyMap = propertyMap;
propertyMap = Collections.unmodifiableMap(innerPropertyMap)
You can obviously replace propertyMap with a custom implementation of map instead. However, this only really works if you want to disable for all callers on the map, disabling for only some callers would be a pain. (I am sure there is a way to do if(caller is parent) then return; else error; but it would be very very very messy). This means the parents use of the class will fail.
Remember, even if you want to hide it from children, if they add themselves to the same package, they can get around ANY restrictions you put with the following:
ThirdPartyClass grandparent = this;
// Even if it was hidden, by the inheritance properties you can now access this
// Assuming Same Package
grandparent.propertyMap.get("Parent-Blocked Chocolate Cookie")
Thus you have two options:
Modify the Parent Object. If you can modify this object (even if you can't make the field private), you have a few structural solutions you can pursue.
Change property to fail in certain use-cases. This will include access by the grandparent and the child, as the child can always get around the parent restrictions
Again, its easiest to think about it like a method: If someone can call it on a grandparent, they can call it on a grandchild.
Use a wrapper. A anti decorator pattern, that instead of adding new methods removes them by not providing a method to call it.
I am in a very early stage of game development. It is some sort of turn based game like Warhammer or Warcraft. Some creatures can regenerate the damage they have suffered and to represent this I have a interface like this
public interface Regenerative {
void regenerates();
}
So a creature that regenerates is
public class SomeMonster() extends BaseCreature implements Regeneative{
//Code
private int hitPoints;
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
The problem I face is that not all the creatures regenerates the same ammount of hit points so I have to place that amount (regenerateValue) somewhere. Since I cannot put it on the interface (because I don't want the ammount to be the same to all the creatures) I have thought in adding a new property to the creature class
public class SomeMonster() extends BaseCreature implements Regeneative{
//Code
private int regenerateValue;
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
but I don't like it this way (why a creature that doesn't regenerate should have a regenerateValue of 0?). I think it is giving a class unnecesary properties and thus a bad design. What do you think is the best approach for this case?
The problem I face is that not all the creatures regenerates the same ammount of hit points so I have to place that amount (regenerateValue) somewhere.
Why does it have to be a field anywhere? Some implementations of the interface might use a different value per instance; others might use a constant value.
This is an implementation detail - and thus inappropriate for the interface. You could potentially put it in an abstract superclass which implements the interface, of course.
Code which knows about the interface almost certainly shouldn't know or care the details of how much a creature regenerates - maybe they regenerate in terms of magic rather than just hit points, for example, or maybe the level of regeneration depends on some other function of their state. Callers shouldn't care.
I would add it to the abstract BaseCreature and not worry about it too much. Your BaseCreature may end up with lots of properties which are effectively "turned off" but the alternative is to create a complex inheritance tree. As Java doesn't support multiple inheritance this will frustrate your ability to abstract all the combinations you might like away.
The solution i use may be a bit over-ingeniered, but this allow for a lot of extension (regeneration, poison, protection...)
I use of interface "CreatureProperties" that define a integer value along with an id, and can perform action on a monster at each turn. You subclass those properties to perform a given property
abstract class CreatureProperties {
protected String id = "";
protectd int propertyValue = 0;
public void actOn(BaseMonster);
// plus setter and getter
}
public RegenerationProperty implements CreatureProperties {
final public REGENERATION_ID = "Regeneration";
int regenerationValue = 0;
public RegenerationProperty(int value){
id = REGENERATION_ID;
propertyValue= value;
}
public void actOn(BaseMonster monster){
monster.setHitPoint(monster.getHitPoints()+propertyValue);
}
}
in the BaseMonster class, you manage a set of MonsterProperty, initially empty.
class BaseMonster {
protected List<CreatureProperties> properties =
new ArrayList<CreatureProperties>();
// plus management of propeties : add remove, iterator...
public void update(){
// perform all properties-linked update to monster
foreach (CreatureProperty property : properties){
property.actOn(this);
}
}
}
in the subclass for SomeMonster, you simply add during instanciation the set of properties for this type of monster.
class SomeMonster extends BaseMonster {
public SomeMonster(){
properties.add(new RegenerationProperty(5)); // presto : monster regenerate
}
}
I'm using the Id in some case where the property is not used each tick (ie nothing in the update), but for example damage reduction (id="LightningReduction"), or to modify the list of existing properties (a property that remove all regenerationProperty and add PoisonProperty of same value...).
I think your design is probably ok, as you would only need to include a regenerateValue in the classes that implement the Regenerative interface. So there would be no need to include a regenerateValue.
Otherwise you could look at more complex design patterns that favor composition over inheritance. This way you could cater for the possibility of dynamically adding Regenerative abilities to a monster along with other 'abilities' during the game, rather than having to recompile the game each time you need to make change the behaviour of your monster.
What if all monster regenerate, but some of them with 0 regenerate value (the same as not regenerating)?
So you don't need the inferface:
public class SomeMonster() extends BaseCreature {
//Code
protected int regenerateValue; //protected, so that subclasses can override the value
public void regenerates(){
hitPoints = hitPoints + regenerateValue;
}
}
The regenerateValue starts with 0, so you have to override the value in subclasses that want to actually regenerate
Edited to remove the " implements Regeneative"
You could add a method in your interface, like getRegnerationValue(), making sure all creatures with that interface have this method that holds the value or formula if that is something you would like to work with.
The question you should ask yourself is this: if a creature should regenerate, how do you know that? Will it implement a different (or extending) base class? one that implements Regenerative?
If the answer is that you will extend the base class (to something like BaseRegeneratingCreature) and all regenerating creatures will extend that class, then this is your answer: BaseRegeneratingCreature should implement that interface, and have all properties required for regenerating.
All non-regenerating creatures should directly extend BaseCreature (or another extending class), and will not need the regeneration related properties.
Then, your base class could have some method like:
OnStartOfTurn();
which will, in BaseRegeneratingCreature, call regenerates() (and then probably call super()), and in BaseCreature do something else or call other methods.