Suppose you have a class Dog, that has
public class Dog {
private String name;
private double age;
// some setters
// some getters
Additionally, you have a class DogHandler, that makes an instance of the Dog d and passes it to Owner
I suppose, i can
... make a copy of a Dog before passing it to Owner, but that's an expensive operation and i'd rather avoid it.
... come up with an interface that Dog implements which contains getters only, cast Dog to that interface and pass the result along
... initialize settable variables in a constructor and simply not allow changes for this instance of an object
Are there any other ways to make sure receiver of the object cant modify it?
How do you take a simple bean containing some data and make it read-only?
This can be achieved in few ways, I can propose you 2 of them:
a) interface with getters is good idea
b) create derived class from Dog which has setters method blocked, like this:
class UnmodifiedDog extends Dog {
public UnmodifiedDog(double age, String name) {
super.setAge(age);
super.setName(name);
}
#Override
public void setAge(double age) {
throw new UnsupportedOperationException();
}
#Override
public void setName(String name) {
throw new UnsupportedOperationException();
}
}
In DogHandler:
Dog createDog() {
return new UnmodifiedDog(10, "Fido");
}
and you can pass this to the Owner:
owner.receiveDog(dogHandler.createDog());
The approaches you mention in the question are pretty much the standard steps to take to make Dog immutable. The only other tip would be to mandate that Dog cannot be overridden by declaring the class to be final.
Among the solutions mentioned here, you can also take advantage of visibility modifiers. If Dog and Owner are in separate packages, you can set the visibility of the mutators to default (package) scope or protected scope.
This will allow you to keep Dog and DogHandler in the same package (and therefore allow them both to mutate the Dog object accordingly), while keeping Owner objects separate (and therefore preventing them from making any modification to the Dog objects).
Here is an example using an interface and package access setters.
package blah.animal;
public interface Dog
{
double getAge();
String getName();
}
package blah.animal;
public class DogImpl implements Dog
{
private double age; // double seems wrong for age.
private String name;
... getters (defined by Dog interface)
// package access setters.
void setAge(double newValue)
{
age = newValue;
}
void setName(String newValue)
{
name = newValue;
}
package blah.animal;
public class DogHandler
{
public static Dog newDog(double age, String name)
{
Dog returnValue = new DogImpl();
returnValue.setAge(age);
returnValue.setName(name);
return returnValue;
}
}
package.blah.somethingelse;
public class Blam
{
private Dog myDog;
public Blam()
{
myDog = DogHandler.newDog(1.4D, "Tippy");
}
}
Related
I have a task that needs to be done but I am really stuck.
Basically, I've some inheritance relations like this:
Animal
Pet WildAnimal
Bird Cat Dog Fish ||Snake Eagle
Animal is the parent of Pet and Wild Animal.
Pet is the parent of Bird, Cat, Dog, Fish.
WildAnimal is the parent of Snake and Eagle.
The task wants me to read inputs from a file which is "input.txt" and create Animal objects.
"input.txt" is like:
kiwi Bird
charlie Eagle
mango Fish
pepper Dog
angle Cat
tweety Bird
bob Dog
ziggy Snake
I can get all of the names but I couldn't figure out how to understand which kind of object every single name represent.
Here is the main method:
public static void main(String[] args) throws IOException {
String s ="";
int nameCounter = 0;
Animal[] animals = new Animal[100];
try{
Scanner input = new Scanner(Paths.get("input.txt"));
while (input.hasNext()) {
s = input.next();
Animal animal = new Animal(s);
animals[nameCounter] = animal;
nameCounter += 2;
}
}catch(Exception e){
e.printStackTrace();
}
}
Here is the animal class:
public class Animal {
private String name;
private int numberOfLegs;
private int numberOfWings;
public Animal(String name){
this.name = name;
numberOfLegs = 4;
numberOfWings = 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNumberOfLegs() {
return numberOfLegs;
}
public void setNumberOfLegs(int numberOfLegs) {
this.numberOfLegs = numberOfLegs;
}
public int getNumberOfWings() {
return numberOfWings;
}
public void setNumberOfWings(int numberOfWings) {
this.numberOfWings = numberOfWings;
}
public void talk(){
System.out.printf("<Silence>");
}
public void fly(){
System.out.printf("%s cannot fly", getName());
}
public void run(){
System.out.printf("%s is running", getName());
}
}
I can add all the other classes if you want but i don't think you're gonna need them.
You have to instantiate objects of your specific class; based on the incoming string.
Example: if the class name from the file is Bird ... then you have to call new Bird() somehow.
There are two ways to get there:
Using reflection (you can actually instantiate classes "by string"; without knowing anything about that class)
By using a switch statement
Reflection is more of an "advanced" topic (and very easy to use the wrong); so I really do recommend you to go for option 2, like:
private Animal createAnimalFor(String className, String animalName) {
switch (className) {
case "Bird": return new Bird(animalName);
...
default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className);
}
}
(the above code is meant as "fyi" - I didn't run it through the compiler; it is meant to give you one idea how this could be done).
Some notes beyond that:
Consider using a final field for those properties of your objects that can't change. You don't need a setter for the name then; just give the name as parameter to the constructor. In other words: only make those fields "changeable" that make sense to be changed. Anything else should better be final.
Instead of using an array with 100 empty slots, you could use a java.util.ArrayList and just add as many new animals as you find in that file.
Consider adding equals/hashCode methods to your Animal class (not mandatory, but you should read why that makes sense very often).
Probably most importantly: consider not putting all those different methods directly into your base class. It might make more sense to create either abstract subclasses that add certain functions, or use interface, like interface FlyingAnymal { void fly() }; which your specific subclasses would then implement. It is not really good practice to put a lot of methods on your base class ... that simply dont make sense for all of the sub classes.
If you really want to use reflection to do so (which I would also discourage), here's sample code :
String name = input.next();
String className = input.next();
// apply transformations to className as needed
Class<Animal> c = (Class<Animal>) Class.forName(className);
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor
Animal a = constr.newInstance(name);
I don't think the code is so complex, but few people have ever used reflection so they'll have problems maintaining it, and it is tightly coupled with your classes definitions so it will probably have to be maintained a lot.
Okay, I want to start off my question with an example of what I'd basically like to do, though it's not working this way.
I want to have an interface IDog that enforces its implementations to have some methods. I also want an superclass AbstractDog implements IDog to give basic attributes and methods to all Dog classes. Then I want to have Subclasses like Poodle extends AbstractDog. My problem here are static methods - I basically want each subclass of AbstractDog to have a different static method but I want to be able to enforce this method from IDog.
So my naïve (and wrong) implementation would be:
public interface IDog {
String getName(); // every dog instance should be able to call name
static String getDescription(); // every dog class should be able to get its description
}
public abstract class AbstractDog implements IDog {
private String name; // every dog instance will have this
public AbstractDog(String name) {
this.name = name;
}
#Override
public String getName() {
return this.name; // every dog instance can call this
}
}
public class Poodle extends AbstractDog {
private static String description = "It's a poodle!"; // all Poodles have the same description
public Poodle(String name) {
super(name);
}
#Override // from IDog
public static String getDescription() {
return description;
}
}
Now, as I said, this is not correct because the AbstractDog class would need a static abstract method getDescription() and IDog needs an implementation of its method and it can't be overridden.
I want to know, if there is a Design pattern which matches my problem: enforcing a set of classes (which could or should have an intermediate superclass) to implement a (different!) static method.
One possibility I have discovered, but I'm not sure if it may be useful or even adequate, would be the use of an enum DogType and then just having a class Dog with a DogType attribute:
public enum DogType {
Poodle("This is a poodle."), Havanese("This is a Havanese.)";
private String description;
private DogType(String description) {
this.description = description;
}
public String getDescription() {
return this.description;
}
}
public class Dog {
private String name;
private DogType dogType;
public Dog(String name, DogType dogType) {
this.name = name;
this.dogType = dogType;
}
public String getName() {
return this.name;
}
public String getDescription {
return this.dogType.getDescription();
}
}
However, this "workaround" loses an ability over my initial idea: I now can't additional functionalities to only one dog class like an instance method void prance() which should only be accessible to Poodle.
Many topics regarding similar questions have refered to the Factory pattern, but I'm not sure how it fits my problem because I don't necessarily need a constructing method. And as the number of dog races rises my code would become very confusing I think. Or maybe I just didn't get how the Factory should be used correctly in my case.
Interfaces are enforced behaviours. Classes are used to specify properties. Static methods get hidden. They are not over-ridden by subclasses. So if you have static methods in your subclasses, but your object reference is of supertype class, then your static method from superclass is invoked. This is class Method hiding, happens with static methods.
I want to know, if there is a Design pattern which matches my problem:
enforcing a set of classes (which could or should have an intermediate
superclass) to implement a (different!) static method.
Sorry. Static methods and inheritance don't go hand in hand.
I now can't additional functionalities to only one dog class like an
instance method void prance() which should only be accessible to
Poodle.
You could introduce a interface Prancable with method void prance().
public interface Prancable{
void prance();
}
public class Poodle extends Dog implements Prancable{
#Override
public void prance(){
System.out.println("My Poodle can prance.");
}
}
You can proceed in this manner for specific methods that add behaviour to different dog breeds.
This is a code smell, there is likely a better way to do it.
If the static method will always return the same thing for all objects of the class, you should just make it a regular get method.
#Override \\ from IDog
public String getDescription() {
return "This is a poodle";
}
If the static variable may be changed then make a new object that holds this class-wide state and give it to each class in the constructor.
ex.
// StringState is a new class that holds a string and has a set and get method
StringState desc = new StringState("original description");
IDog dog1 = new Poodle(desc);
IDog dog2 = new Poodle(desc);
// prints original description
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());
desc.set("New description");
// prints new description, since both objects share the same
// StringState,changing it here changes it in all of them.
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());
I'm not sure if these question is still appropriate to be asked as there could be an answer already. But i still dont understand the concept of inheritance when it comes to attributes in parent and child class relationship. Please note the example below.
class Animal{
public int lifeSpan = 50;
public String imAn(){
return "I'm an Animal";
}
}
class Elephant extends Animal{
public int lifeSpan = 100;
public String imAn(){
return "I'm an Elephant";
}
}
public class Test{
public static void main(String args[]){
Animal animal = new Elephant();
System.out.println(animal.imAn()+" and i live around "+animal.lifeSpan+" years");
}
}
Answer would be : I'm an Elephant and i live around 50 years.
I do understand the virtual method invocation concept here, but what makes it not load the lifeSpan attribute of child class. Does this means the class attributes are not polymorphic?
Does this means the class attributes are not polymorphic?
No, fields aren't polymorphic. You've actually got two fields in your Elephant class - one declared in Animal and one declared in Elephant, which hides the one in Animal. That's the problem. You should get rid of the declaration of lifeSpan in Elephant, and instead initialize the one remaining field in a constructor.
You should also get into the habit of making fields private - and final, where possible. Assuming you really want to have a method to describe the name (rather than a field, which would be more usual) I would write your code as:
class Animal {
private final int lifeSpan;
public Animal() {
// Default to a life-span of 50
this(50);
}
public Animal(int lifeSpan) {
this.lifeSpan = lifeSpan;
}
public String getName(){
return "Animal";
}
public int getLifeSpan() {
return lifeSpan;
}
}
class Elephant extends Animal {
public Elephant() {
// Give every elephant a life-span of 100.
super(100);
}
#Override public String getName() {
return "Elephant";
}
}
public class Test {
public static void main(String args[]){
Animal animal = new Elephant();
System.out.printf("I am an %s and I live around %d years%n",
animal.getName(), animal.getLifeSpan());
}
}
I have two objects which use really similar methods, save for one line. For example:
public class Cat extends Animal
public class Dog extends Animal
And they both use a breed method in the abstract class Animal. One calls new Dog(), and the other new Cat(). Right now I just have it declared as abstract public void breed(); in Animal, but is there a way I can generalize it so I don't have to make it an abstract method to be overridden?
There are many ways to do this, assuming by breed you mean "create children of me."
Reflection
First is to use reflection. If you have a no-args constructor for your classes, this is as easy as calling Class.newInstance:
public Animal breed() {
try {
return (Animal) getClass().newInstance();
} catch (Exception ex) {
// TODO Log me
return null;
}
}
If you don't have a no-args constructor in all your subclasses, you'll have to have a uniform constructor across all your subclasses. For example, if you have Cat(int, String) and Dog(int, String), then you need to get the constructor via Class.getConstructor and invoke newInstance on that:
return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed");
int and String here may be age and name, for example. This is how you do this with reflection.
Providers
Another way is to use this simple interface:
public interface Provider<T> {
T create();
}
Then have your abstract class take an instance of this in its constructor:
public abstract class Animal {
private final Provider<Animal> animalProvider;
protected Animal( ... , Provider<Animal> animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
Then your subclasses will pass a Provider<Animal> to the superclass which will create new instances of the subclass:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new DogProvider());
// ...
}
private static class DogProvider implements Provider<Animal> {
public Animal create() {
return new Dog( ... );
}
}
}
Do the same for other subclasses as well.
Note: if by breed you mean "get the type of me," then you should edit your question to say so. If this is what you meant, then this is a viable solution:
public abstract class Animal {
protected final Breed breed;
protected Animal( ... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
I recommend following the get/set conventions for data container methods. Java has bean classes designed to handle these naming conventions, and it's more or less a standard across many platforms. For your subclasses:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}
Actually, yes you can. You need to use reflection so performance could be a little iffy, but this (untested) should work:
public abstract class Animal{
public Animal breed(){
return getClass().newInstance();
}
//other methods
}
This will return a new instance of the actual calling type, not the type of Animal (where it's implemented).
This is actually somewhat similar to the Prototype Pattern. Although in this case you're creating a new instance, not copying an existing instance.
Edit
As #FrankPavageau pointed out in the comments, rather than masking an exception in the constructor, you can achieve the same result by using
public abstract class Animal{
public Animal breed(){
return getClass().getConstructor().newInstance();
}
//other methods
}
Which will wrap any exception thrown in an InvocationTargetException which is a bit cleaner and probably easier to debug. Thanks #FrankPavageau for that suggestion.
No there isn't. You will have to have something like what you have done as below
I think you want to have in your abstract class
public abstract Breed getBreed();
and then in each sub class have
public Breed getBreed() {
return new DogBreed();
}
and a similar one returning cat.
or
Have a protected field in the Animal class called breed. This could then be initialised in each of the subclasses. This would remove the need for an abstract method. For example
public abstract class Animal {
Breed breed;
...
}
and then in Dog have
public class Dog extends Animal {
public Dog() {
breed = new DogBreed();
}
}
and have something similar to Cat.
It might be worth you while also passing in the breed to the Dog/Cat ctor so that you can create Dog objects of different breeds rather than restricting your model to just one breed of Dog
I am not sure Breed is necessarily modelled correctly in your example. Do you really want new Dog() to be a breed? Or do you mean type? In which case it is just an animal and the abstract method returning animal is the way to go.
I wonder how can I remove object in other method, for example I want to delete the dog object in deleteObject method, but it just deletes the current reference to the object!
Is there any solution or not?
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Max");
deleteObject(dog);
System.out.println(dog.toString()); //it still exists! I want to remove it
}
public static void deleteObject(Dog dog) {
dog = null; //I want to remove this object but it deletes just this method's reference
}
}
class Dog {
private String name;
public Dog(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
An object is "deleted" (or more specifically becomes eligible for deletion by the garbage collector) when there are no more references to it. In your example there are 2 references pointing at the same object (the dog reference in your main method and the dog reference in your deleteObject method). When you set dog to null in deleteObject the dog reference in main is still pointing to the object.
You can just set the dog reference to null in main and this will make the object elligible for garbage collection. Or make the dog reference a class variable i.e. declared outside any method - then main and delteObject can work with the same dog reference.
Why do you want to delete the object anyway? At the end of your method, all local references become out of scope anyway and the object will become elligible for garbage collection.
I have a solution, but maybe it is just too overkill for your problem; it involves WeakReferences:
public class Pound{
public static WeakReference<Dog> adopt(String name){
Dog newDog = new Dog(name);
dogList.add(newDog);
return new WeakReference<Dog>(newDog);
}
public static void sacrifice(WeakReference<Dog> dogRef){
Dog sadPuppy = dogRef.get();
dogList.remove(sadPuppy);
}
private static List<Dog> dogList = new ArrayList<Dog>();
public class Dog{
public String getName(){
return this.name;
}
private Dog(String name){
this.name = name;
}
private String name;
}
}
The trick here is to make sure that the only strong references to Dog instances are in the Pound class (or are local references to a method), and use WeakReferences everywhere else. That way, when you call the method
sacrifice(WeakReference<Dog> dog)
from anywhere in your code, you'll be removing the only strong reference to it, making it elligible for GC. So, if you want to dispose of a Dog instance from any method:
class Main{
public static void main(String ... args){
WeakReference<Dog> max = Pound.adopt("Max");
//This line prints "Max"
System.out.println(max.get().getName());
meanMethod(max);
//Max is now dead, so you get a NullPointerException
System.out.println(max.get.getName());
}
public static void meanMethod(WeakReference<Dog> dog){
Pound.sacrifice(dog);
//From this point, dog is no more ='(
}
}
You can create dog instances in one method and dispose of them in another, as long as you only have one permanent strong reference (in the list where the dogs are being stored), and you provide methods to add and remove them from the list. Of course, this is all useless if you do:
Dog strongDog = weakReferenceToDog.get();
in your main method.
Also, you have to make checks in every part of your code where you use get() for null values, and you'd need some method for constantly cleaning the ReferenceQueue that holds the dead WeakReferences.
Depending on what you actually intend to do, this could be too much and you'd be better with another solution, or forgetting completely about this, but at least this is the only way I can think of that could work.
In java Object are garbage collected(in your words deleted) by GC. When no active reference to that object exist it is automated process. Moreover you can't be 100% sure that when no reference exist it has been deleted its just request.
public class Main {
static Dog dog = null;
public static void main(String[] args) {
dog = new Dog("Max");
dog = deleteObject(dog); //really unnecessary
if(dog==null)
{
System.out.println("I AM DEAD!");
}
else
{
System.out.println(dog.toString());
}
}
public static Dog deleteObject(Dog dog) {
dog = null;
return dog;
}
}
class Dog {
private String name;
public Dog(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}