How to protect class to be instantiated directly - java

How can I change this implementation:
public interface Animal()
{
public void eat();
}
public class Dog implements Animal
{
public void eat()
{}
}
public void main()
{
// Animal can be instantiated like this:
Animal dog = new Dog();
// But I dont want the user to create an instance like this, how can I prevent this declaration?
Dog anotherDog = new Dog();
}

Create a factory method and protect the constructor:
public class Dog implements Animal {
protected Dog () {
}
public static Animal createAsAnimal () {
new Dog ();
}
}

You can do it as follows by creating a factory method :
public interface Animal {
public void eat();
public class Factory {
public static Animal getAnimal() {
return new Dog();
}
private static class Dog implements Animal {
public void eat() {
System.out.println("eats");
}
}
}
}
The Dog class is not visible to the user.
To run :
Animal dog= Animal.Factory.getAnimal();
dog.eat();//eats

Related

Autowired bean based on annotation value type

I have the following classes:
public abstract class Animal {
public abstract void call();
}
public class Dog extends Animal {
#Override
public void call() {
System.out.println("Dog was called");
}
}
public class Cat extends Animal {
#Override
public void call() {
System.out.println("Cat was called");
}
}
public #interface AnimalAnnotation {
AnimalType value() default AnimalType.DOG;
}
public enum AnimalType {
DOG,
CAT
}
In a Configuration class I am creating a bean for the two type of Animal inheritors:
#Configuration
public class AnimalConfiguration {
#Bean
public Animal initDog() {
return new Dog();
}
#Bean
public Animal initCat() {
return new Cat();
}
}
My intention here is to autowired a bean with dynamic type as it follows:
public class Main {
#Autowired
#AnimalAnnotation(AnimalType.CAT)
private Animal animal; // the instance should be the Cat one
public void perform() {
animal.call(); // In the console we should see "Cat was called".
}
}
This is a example code which describes my intention, which it could be wrong.
Can be this be implemented and what is the correct approach?
How about using a #Qualifier? That may work. You would have to give your beans a name like
#Bean("cat")
public Animal initCat() {
return new Cat();
}
and then when autowiring you would have:
#Autowired
#Qualifier("cat")
private Animal animal;
I think the easiest way will be to use #Qualifier annotation, e.g.:
#Autowired
#Qualifier("initDog")

do i have to use instanof in this problem? or how should i code instead?

i wrote an example code for my question. i want to use polimorfism and i try to change a variable by the type of object. This code is working but is it the best way of that? Should i use a common method in both classes to return the variable? Thanks
package example;
import java.util.Scanner;
class Animal{}
class Dog extends Animal{}
class Bird extends Animal{}
public class Example {
public static void main(String[] args) {
Animal a;
int leg=0;
Scanner k=new Scanner(System.in);
String s=k.next();
if(s.equals("dog")) a=new Dog();
else a=new Bird();
if(a instanceof Dog) leg+=4;
else if(a instanceof Bird) leg+=2;
System.out.println(leg);
}
}
You should place common functionality into the parent class Animal and implement specific functionality into child classes Bird and Dog.
abstract class Animal {
abstract int legs();
}
class Bird extends Animal {
#Override
int legs() {
return 2;
}
}
class Dog extends Animal {
#Override
int legs() {
return 4;
}
}
There's no need for instanceof, just call the legs method of Animal and the implementing class will output the correct value.
public class Example {
public static void main(String[] args) {
Animal animal;
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
if(s.equals("dog")) {
animal = new Dog();
} else {
animal = new Bird();
}
System.out.println(animal.legs());
}
}
Put the common attributes and behaviors to the parent
abstract class Animal {
public abstract int getLegs();
}
class Bird extends Animal {
#Override
public int getLegs() {
return 2;
}
}
class Dog extends Animal {
#Override
public int getLegs() {
return 4;
}
}
, Add a method that creates an object based on parameter this is Factory Design pattern factory_pattern.htm
public static void main(String[] args) {
Animal animal;
Scanner scanner = new Scanner(System.in);
String animalType = scanner.next();
animal = getAnimal(animalType);
if (animal != null)
System.out.println(animal.getLegs());
scanner.close();
}
static Animal getAnimal(String type) {
if(type==null || "".equals(type)) return null;
Animal animal;
if ("dog".equalsIgnoreCase(type)) {
animal = new Dog();
} else if("bird".equalsIgnoreCase(type){
animal = new Bird();
}
return animal;
}
The number of legs the animal has should be contained within the subclass of Animal rather than set from the outside as you've currently got. Something like:
public abstract class Animal {
protected int numLegs;
public int getNumLegs() {
return numLegs;
}
}
public class Dog extends Animal {
public Dog() {
numLegs = 4;
}
}
Good luck!

Java main class not found(error free)

here is my source code i named my Project as Animal but when I run it. There is an error locating my MAIN CLASS. Please help me. I am still a beginner and i am open to learn a lot more.
package animal;
public class Animal {
public Animal() {
System.out.println("A new animal has been created!");
}
public void sleep() {
System.out.println("An animal sleeps...");
}
public void eat() {
System.out.println("An animal eats...");
}
}
public class Bird extends Animal {
public Bird() {
super();
System.out.println("A new bird has been created!");
}
#Override
public void sleep() {
System.out.println("A bird sleeps...");
}
#Override
public void eat() {
System.out.println("A bird eats...");
}
}
public class Dog extends Animal {
public Dog() {
super();
System.out.println("A new dog has been created!");
}
#Override
public void sleep() {
System.out.println("A dog sleeps...");
}
#Override
public void eat() {
System.out.println("A dog eats...");
}
}
public class MainClass {
public static void main(String[] args) {
Animal animal = new Animal();
Bird bird = new Bird();
Dog dog = new Dog();
System.out.println();
animal.sleep();
animal.eat();
bird.sleep();
bird.eat();
dog.sleep();
dog.eat();
}
}
Please help me with this.
As studied your code,found the error only on class modifier(public) you declared.
" you can have only one public class modifier in a java source file"
We can declare one class in a single source file with these constraints:
Each source file should contain only one public class and the name
of that public class should be similar to the name of the source
file.
If you are declaring a main method in your source file then main
should lie in that public class.
If there is no public class in the source file then main method can
lie in any class and we can give any name to the source file.
So..
Your code is..
class Animal {
public Animal() {
System.out.println("A new animal has been created!");
}
public void sleep() {
System.out.println("An animal sleeps...");
}
public void eat() {
System.out.println("An animal eats..."); }
}
class Bird extends Animal {
public Bird() {
super();
System.out.println("A new bird has been created!");
}
#Override
public void sleep() {
System.out.println("A bird sleeps...");
}
#Override
public void eat() {
System.out.println("A bird eats...");
}
}
class Dog extends Animal {
public Dog() {
super();
System.out.println("A new dog has been created!");
}
#Override
public void sleep() {
System.out.println("A dog sleeps...");
}
#Override
public void eat() {
System.out.println("A dog eats...");
}
}
public class MainClass {
public static void main(String[] args) {
Animal animal = new Animal();
Bird bird = new Bird();
Dog dog = new Dog();
System.out.println();
animal.sleep();
animal.eat();
bird.sleep();
bird.eat();
dog.sleep();
dog.eat();}
}
Ideally, you should have Bird, Dog, and Animal in their own files on the same directory. Then you create one more class, a tester class, that has a main function, and since it's in the same directory as Bird, Dog, and Animal, it can access them and you can do what your main class does now. If you NEED to have it all in one file, make every class header just class Bird {, etc. Then rename the file to MainClass.java and it'll run.
Please refer: Can a java file have more than one class?
For short: there can only be one public top-level class per .java file.
So, you should edit your code:
package Animal;
class Animal {
public Animal() {
System.out.println("A new animal has been created!");
}
public void sleep() {
System.out.println("An animal sleeps...");
}
public void eat() {
System.out.println("An animal eats...");
}
}
class Bird extends Animal {
public Bird() {
super();
System.out.println("A new bird has been created!");
}
and so on ...

Superclass/Subclass methods [duplicate]

This question already has answers here:
why java polymorphism not work in my example
(3 answers)
Closed 6 years ago.
I have a situation
public class Animal
{
String noise;
public String makeNoise()
{
return noise;
}
}
Then there will be a subclass with the concrete definition of the noise.
public class Dog extends Animal{
String noise = "woof";
}
also
public class Cat extends Animal{
String noise = "meow";
}
What I want to do is
Animal cat = new Cat();
cat.makeNoise(); // This will be 'meow'
and
Animal dog = new Dog();
dog.makeNoise(); // This will be 'woof'
Basically, I don't want to repeat the makeNoise() method when I create an animal. However, this will not work. (Noise is an empty string)
I could use a static object like
static String NoiseDog = "woof"
static String NoiseCat = "meow"
but then again I have to write the makeNoise() method for each animal. Is there a better way to architect this?
If you want to force all sub-classes of Animal to have a noise defined, you can enforce that in the constructor:
public abstract class Animal {
private final String noise;
public Animal(final String noise) {
this.noise = noise;
}
public String makeNoise() {
return noise;
}
}
Then Dog:
public class Dog extends Animal {
public Dog() {
super("woof");
}
}
And Cat:
public class Cat extends Animal {
public Cat() {
super("meow");
}
}
And to test it out:
public class Test {
public static void main(String[] args) {
final Animal dog = new Dog();
System.out.println(dog.makeNoise());
final Animal cat = new Cat();
System.out.println(cat.makeNoise());
}
}
Output:
woof
meow
public class Cat extends Animal{
String noise = "meow";
}
This creates an instance variable named "noise" that hides the superclass variable.
Instead, you need this to set the superclass value:
public class Cat extends Animal{
public Cat() {
noise = "meow";
}
}
Make the Animal class abstract. This way, there can be no such thing as an Animal object which calls makeNoise.
Then, set the noise String to a value within the constructor of each subclass as appropriate to that animal's sound.
Alternatively, you could implement an interface like so:
Animal:
public interface Animal {
public String makeNoise();
}
Dog:
public class Dog implements Animal {
public String makeNoise() {
return "woof";
}
}
Cat:
public class Cat implements Animal {
public String makeNoise() {
return "meow";
}
}
Test:
public class Test {
public static void main(String[] args) {
Animal dog = new Dog();
System.out.println(dog.makeNoise());
Animal cat = new Cat();
System.out.println(cat.makeNoise());
}
}
Output:
woof
meow

In an ArrayList of Object, how can I convert Object into one of 3 instance of classes contained in an ArrayList?

I'm doing a simple Zoo application to understand oriented object concepts in Java.
My model is as follow:
1) A Zoo has a number of Cages
2) A Cage has a a mixture of Feline, Primate or Bird
3) An Animal can eat, sleep or drink
4) Feline extends Animal (Do extra Feline stuff)
5) Primate extends Animal (Do extra Primate stuff)
6) Bird extends Animal (Do extra Bird stuff)
The problem:
While it's pretty easy to handle x number of cages in a zoo (ArrayList of Cage), I'm struggling with the Animals in Cage.
I found out that I need to have an ArrayList of Object.
So far so good, but when I try to obtain my animal back and have him scratch a post, it's not a Feline anymore, it's an Object.
public class Cage{
private String name;
private ArrayList<Object> animals = new ArrayList<Object>();
public Cage(String name){
this.name = name;
}
public void addFeline(String name){
Feline newFeline= new Feline(name);
this.animals.add(newFeline);
}
public void addPrimate(String name){
Primate newPrimate= new Primate(name);
this.animals.add(newPrimate);
}
public void addBird(String name){
Bird newBird= new Bird(name);
this.animals.add(newBird);
}
public void removeAnimal(int index){
this.animals.remove(index);
}
public Object getAnimal(int index){
Object myAnimal = this.animals.get(index);
return myAnimal;
}
}
And the way I call it:
Zoo myZoo = new Zoo("My Zoo");
myZoo.addCage("Monkey Exhibit");
Cage myCage = myZoo.getCage(0);
myCage.addFeline("Leo");
Object MyAnimal = myCage.getAnimal(0);
The Question: How can I turn Object back into instance of class Feline so it can Scratch a Post?
I think the best way to approach this problem would be using the Strategy design pattern.
Feline, Primate and Bird should implement an interface Animal. The Cage would then have a method public void addAnimal(Animal animal);
The object creation for Feline, Primate and Bird should be outside of Cage.
I have put together some code if this can help. I would design the application similar to something below.
Behaviours should be encapsulated using interfaces. e.g. EatingBehaviour
public interface Animal {
public String getName();
}
public interface EatingBehaviour {
public void howManyTimes();
}
public class RealLionEatingBehaviour implements EatingBehaviour{
#Override
public void howManyTimes() {
System.out.println("I eat once a day");
}
}
public class ToyLionEatingBehaviour implements EatingBehaviour {
#Override
public void howManyTimes() {
System.out.println("I never eat! I am a toy lion.");
}
}
public abstract class Feline implements Animal{
public abstract void scratchPost();
private EatingBehaviour eatingBehaviour;
public EatingBehaviour getEatingBehaviour() {
return eatingBehaviour;
}
public void setEatingBehaviour(EatingBehaviour eatingBehaviour) {
this.eatingBehaviour = eatingBehaviour;
}
}
public class Lion extends Feline {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
Lion (String name) {
this.name=name;
}
public void scratchPost(){
System.out.println(getName() + " Lion Scratching Post!");
}
}
public class AnimalFactory {
public static Animal getAnimalInstance(String type, String name){
Animal animal=null;
if ("lion".equalsIgnoreCase(type)) {
animal = new Lion(name);
}
return animal;
}
}
import java.util.ArrayList;
import java.util.List;
public class Cage {
private List<Animal> animals = new ArrayList<Animal>();
public void addAnimal(Animal animal) {
animals.add(animal);
}
public void removeAnimal(int index){
this.animals.remove(index);
}
public Animal getAnimal(int index){
return this.animals.get(index);
}
}
public class Zoo {
public static void main(String args[]) {
Cage cage = new Cage();
Animal animal = null;
animal = AnimalFactory.getAnimalInstance("Lion", "Sweety");
cage.addAnimal(animal);
Animal animalFromCage = cage.getAnimal(0);
if (animalFromCage instanceof Feline) {
Feline feline = (Feline) animalFromCage;
feline.setEatingBehaviour(new RealLionEatingBehaviour());
feline.scratchPost();
feline.getEatingBehaviour().howManyTimes();
feline.setEatingBehaviour(new ToyLionEatingBehaviour());
feline.getEatingBehaviour().howManyTimes();
}
}
}
Use a cast:
Object myAnimal = myCage.getAnimal(0);
Feline f = (Feline) myAnimal;
private List<Animal> animals = new ArrayList<Animal>();
public void findAnimal(int index) {
Animal myAnimal = animals.get(index);
if (myAnimal instanceof Feline) {
Feline feline = (Feline) myAnimal;
//do the work with Feline
} else if (myAnimal instanceof Primate) {
//do the work with Primate
}
// continue with the other types.
}
this will avoid a unexpected classcast exception. Since you know the type use the super type (Animal) in the Arraylist instead fo Object. if it is Obejct you can add anything to the List.
You should use an ArrayList<? extends Animal> instead of ArrayList<Object>. You would then cast a return value to the appropriate subclass of Animal.

Categories

Resources