I currently have a parent class which has two subclasses and what I essentially want to do is have them both inherit a shared variable (a float). I need to set the value of the float in subclass1 and then use the value of the float in subclass2. I should add that these are all android activities and that subclass1 is at the beginning of a chain of activities and subclass2 is at the end of this chain, all the activities in between are also children of the same parent class.
What I currently have is something similar to the following:
(I've left a lot of the other code out this is just the bare bones)
class activityParent extends Activity{
public static float value;
public void setValue(){
//grab the value from phone (ill leave this code out and will hardcode a value below as an example)
value = 0.6f;
}
public void useValue(){
//where i use the value in another function here
otherFuncion(value);
}
}
class subclass1 extends activityParent
{
#Override
public void onCreate(Bundle bundle){
setValue();//need this to be initialized first
super.onCreate(bundle);
}
}
class subclass2 extends activityParent{
//some previous code here
//i need to use the value just before the activity finishes
useValue();
finish();
}
That float value is never used anywhere else.
This approach just seems wrong and I know it but I'm not sure how to go about implementing this properly.
I was thinking about passing data with intents but as mentioned the two subclasses arent in direct contact with each other, theres a series of activities between them and I'd rather not have to string this data through them all just to reach the end.
There is FAQ discussed in below link.
How do I pass data between Activities/Services within a single application?
Ideally, since you want to share a primitive data type (a float), Intent is recommended. But since this does not fit well with your requirement, you may skip this.
Next, using "static" (which you are currently doing) is also fine. You can access these static fields from any other class in your application.
But, if you want to have an alternate, then "Singleton" class can be used. This is a class that is designed to have only one instance.
public class Singleton {
private static Singleton INSTANCE ;
private Singleton() {}
public static synchronized Singleton getInstance() {
if(INSTANCE == null){
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
It has a static method with a name such as getInstance() that returns the instance; the first time this method is called, it creates the global instance.
For example activity subclass1 may retrieve the instance and call setValue(0.6); later activity subclass2 may retrieve the instance and call getValue() to retrieve the last set value.
Be very carefull with a cascade of classes. The onCreate() of a SubClass1 calls super.onCreate() which is the onCreate() of ActivityParent. This may trigger a chain reaction (the intent calling ActivityParent is still available to onCreate()).
Related
Imagine I have an abstract class like this:
public abstract class Device {
public Device(DeviceModel model){
// ...
}
public abstract boolean isBuildable();
}
Then I have an implementation of it that might look like this:
public final class Floor extends Device {
// ...
#Override
public void boolean isBuildable(){
return false;
}
}
Here, each Device subclass returns either true or false to #isBuildable(). But each instance of Floor always returns false. Another implementation of Device may return true. That sounds like a static data : it does not depends on the current instance, but on the type of the Device.
Currently, I'm creating an instance of the class to get its value, as #isBuildable() isn't static. But I think that's poor code design.
So, what I'm trying to achieve here is like creating abstract static method. I've seen this question that doesn't help so much. I would forces the implementation of #isBuildable (this time as static) in all subclasses of Device, so that I can invoke Floor.isBuildable() or something else of the same kind.
Here I can't control all the source, so I can't use reflectivity on that.
Hope you understand this weird question !
If you need to store class-specific (not instance-specific) information, custom annotations may be the way to go.
This require a function using reflection to access that piece of information, which could be overkill in a small project, but should be no problem in a larger framework or similar project.
In Java, static methods cannot override other static methods, so what you want to do is not possible.
Since Java has no real type variables (the type variables used for generics do not survive until run time) you would need an instance anyway to determine which overridden static method to call.
Suppose you have a class Device with two subclasses, Floor and Ceiling, all of which have a method called foo(). Since there are no run-time type variables, T.foo() cannot work, and Device.foo(), Floor.foo() and Ceiling.foo() all specify exactly which method to call.
There are a few solutions/workarounds:
Call the right method through reflection. You will lose any static type checking.
Introduce a companion enum or class which contains the information about your types. For example:
public class DeviceType {
private final boolean buildable;
private DeviceType(boolean buildable) {
this.buildable = buildable;
}
public boolean isBuildable() {
return buildable;
}
}
public class Floor extends Device {
public static final DeviceType DEVICE_TYPE = new DeviceType(false);
...
}
Now you can pass around Floor.DEVICE_TYPE as a kind of representation of the class which contains the information you want.
I have a method which adds Objects to an static list like this:
#PostConstruct
protected void registerToTransactionList() {
TransactionValidator.registerTransactionList(this);
}
registerTransactionList method just adds "this" to the static list, this method is in BalanceTransactionValidator class which extends TransactionValidator (owner of static list),the problem is all subclasses of BalanceTransactionValidator class are added to static list either,and if I override registerToTransactionList method in them like this:
#Override
#PostConstruct
protected void registerToTransactionList() {
}
It doesn't add subclasses but doesn't add BalanceTransactionValidator either. Can anybody help me on this? Please notice sublasses are overriding this method by default.
make the method private to block the visibility
private void registerToTransactionList() {
}
or make the method final to block it from been override
protected final void registerToTransactionList() {
}
There are two ways of achieving that:
Keep your method as it is; but then you have to actively check for the type of your objects before externally calling that method
Change your whole logic and make that method private
It won't help to make the method final as suggested in one of the comments - your problem is not that subclasses are overwriting that method; in essence, you have a design problem: you wish that subclasses should not invoke that method at all.
So, the only real option that makes sense here is "2.". You see, by having public method on a class that you want to be extended you are implicitly saying: it is perfectly fine to call that method; on any object that is instance of the base class (or child class!).
And in your case, that is not true: you actually do not want that the code behind this method runs for child classes. Then you shouldn't put that method in the list of public/protected methods of your base class!
Finally: you might want to step back and do some reading about good OO design. Class hierarchies do not fall from the sky: you willfully design them for a certain purpose. In other words: there is more to inheritance than just putting some "A extends B" on your class declaration. You have to understand each and every method on your B class; and how your child classes should deal with them!
EDIT: after some more thinking, I guess you are doing things "the wrong way", like:
class BaseClass {
public final void doRegistration() {
BaseClass toRegister = getObjectForRegistration();
if (toRegister != null) { ... register toRegister ...
}
protected BaseClass getObjectForRegistration() {
return null;
}
With that code, you could then put
protected BaseClass getObjectForRegistration() {
if (this instanceof ClassThatShouldBeRegistered) {
return this;
}
return null;
}
into that one class that wants to be registered. Probably there could be even nicer ways of doing so; but after some thinking I don't see how we could avoid the instanceof. But the above code should work; and it only requires specific code only in your base class and in that one class that wants to register something.
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 need to get a reference to the shared prefs from inside an abstract class called A that does not extend anything.
I cannot pass a Context object to this class to get the shared prefs because being abstract, I don't instantiate it. I created class A to be extended by other POJOs that share a single attribute, which is the uuid. The UUID is generated once in the app on its first run, which is why I store it in the shared prefs. In class A's constructor, I'm hoping to set the uuid based on what is in the shared prefs.
public abstract class A {
private String uuid;
public A() {
// this is how I'm hoping to use the shared preferences
this.uuid = sharedPrefs.getString("KEY_UUID", "null");
}
// getter and setter
}
One suggestion I found is to extend Application, say in a class called App, and include an attribute android:name=".App" in the <application> tag in the manifest. I imagine App will be written like this:
public class App extends Application {
private static App app;
public void onCreate() {
this.app = this;
}
public static App getApp() {
return app;
}
}
...so that from inside class A, I can do this:
this.uuid = App.getApp().getSharedPreferences("prefs_name.txt", Context.MODE_PRIVATE).getString("KEY_UUID", "null");
However, doesn't the non-final static field app lose its reference to the App and become null when Android kills off the process or when the phone restarts? How can I get a reference to the shared prefs without using this method? Or should I just manually write the UUID to a file?
Modify your App class to something like this:
public class App extends Application
{
private static Context context;
#Override
public void onCreate()
{
super.onCreate();
App.context = getApplicationContext();
}
public static Context getStaticContext()
{
return App.context;
}
}
I cannot pass a Context object to this class to get the shared prefs because being abstract, I don't instantiate it.
Sure you can. Put Context as a parameter on the constructor. Or, put SharedPreferences as a parameter on the constructor, if you prefer. Your subclasses' constructors will need to take the same parameter and pass it to the super() call.
However, doesn't the non-final static field app lose its reference to the App and become null when Android kills off the process or when the phone restarts?
Well, the whole process is gone. Saying that it loses "its reference to the App and become null" is akin to saying that a person at ground zero of a nuclear blast will get a sunburn just prior to being vaporized -- while probably true, the point is a bit moot. :-)
Providing finish() and this.finish() in onPause() or onStop() method is same?
Yes. Please become familiar with meaning of this. -> it's value is the reference to the current object. For example, if you have a class named Foo, and it has method named method(), then this in it would be a reference to a instance of the Foo (that is: a Foo object). Usually you do not need to use this.
this in any context refers to the containing class. So, if you are using the method inside an Activity, then this.finish() is same as finish(). However, if you are using this in a different class type, you may not have this.finish()
Even though the question is 3 years old.I prefer to torch some light over the present and future researchers.
this is just an object reference.You don't have to use this every time ,other than you need to get a reference of parent class from a child class instance.
Let's consider an example when using Thread class.
public class A
{
public A()
{
new Thread(new Runnable()
{
public void start()
{
B child=new B(A.this);//In this scenario,'A.this' refers to the parent class 'A' in which the 'Thread' class instantiated.If you simply pass 'this' ,then it would refer to the 'Thread' class as this statement executed in the current scope.
}
}).start();
}
}
public class B
{
A parent;
public B(A parent)
{
this.parent=parent;//'this' refers to the class B ,so that it can access the global variable 'parent' ,then assigns it with the local variable 'parent' passed through the constructor.
}
}
Like listed above ,there are different usages of this keyword.Its better to refer the oracle's documentation over here https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
finish() and this.finish() is the same.
For the other part of the question, please read about the Activity lifecycle.
In your case It's the same. It's sometimes important to use this->... if you have an member and an method parameter with the same name like in the following example:
class foo{
int number;
void setNumber(int number);
}
so you can write in your method
void foo::setNumber(int number)
{
this->number = number;
}
And so It's clear which element you have used. But be careful don't use the same names it's not really nice.