If there is an enum,
public enum Animal {
DOG,
CAT;
}
If I'm understanding enums correctly, we can convert them in equivalent class, something like -
public class Animal {
private static final DOG = 1;
private static final CAT = 2;
}
Is this the correct representation, or I'm missing anything here?
Thanks.
Not exactly. Here is how it will look like:
public class Animal extends Enum<Enum<Animal>> {
public static final DOG = new Animal("DOG", 0);
public static final CAT = new Animal("CAT", 1);
private static final Animal[] values = new Animal[] {DOG, CAT};
private Animal(String name, int ordinal) {super(name, ordinal);}
public static Animal valueOf(String name) {return Enum.valueOf(Animal.class, name)}
public Animal[] values() {return values;}
}
Class java.lang.Enum holds ordinal and name and provides methods that can access them.
No, your code shows how things ware organized before enum was added in Java 1.5.
Your enum values needs to be public not private because you want to make them accessible everywhere.
Also they value is instance of your enum class, not integer (you may want to invoke some methods on these instances like TimeUnit.SECONDS.toMinutes(120); where you invoke toMinutes on instance SECONDS)
So your code looks more like
public class Animal extends Enum<Animal>{
public static final Animal DOG = new Animal();
public static final Animal CAT = new Animal();
//rest of code added by compiler, like
// - making constructor private
// - handling `ordinal()`
// - adding `valueOf(String) ` and `values()` methods
}
Related
My sample code structure is like this. There is one parent class Building and one subclass House.
Buiding
public class Building {
private String name;
private int noOfHouses;
}
House
public class House extends Building {
private String houseNumber;
}
I want to write a generic method so that i can access the subclass method also.
something like this.
public <T> void construct(T a){
System.out.println(a.getHouseNumber());
}
Please help.
In fact your example does not show the need of generics. You can use:
public static void construct(House a){
System.out.println(a.getHouseNumber());
}
The same thing, unnecessarily complicated to use generics would also work fine:
public static <T extends House> void construct(T a){
System.out.println(a.getHouseNumber());
}
You can't, and shouldn't do that. It's a bad idea to make parent classes aware of child classes' own concrete methods.
You can use a bounded parameter, if this method is in House, or any other class that doesn't complicate the parent/child relationship:
public static <T extends House> void construct(T a){
System.out.println(a.getHouseNumber());
}
The same thing can be done if the parent is abstract, as suggested above:
public abstract class Building {
private String name;
private int noOfHouses;
public abstract String getHouseNumber();
public static <T extends Building> void construct(T a){
System.out.println(a.getHouseNumber());
}
}
Note that the parent doesn't have to be abstract, as long as it's OK with your design
Generics have nothing to do with this problem. Java provides you with the facility of RunTimePolymorphism, but you can't invoke child's specific method using parent reference.
Consider the following case:
Building b = new House(); //Fine
b.getHouseNumber() // Compiler will be happy only if getHouseNumber is in Building.
I agree with Ernest Kiwele, but if you want to access a method that will be part of a subclass you can override a method in each subclass
abstract class Building{
private String name;
private int noOfHouses;
public abstract String getHouseNumber();
public void construct(){
System.out.println( getHouseNumber() );
}
}
public class House extends Building{
private String houseNumber = "houseNumber";
public String getHouseNumber(){
return this.houseNumber;
}
public static void main(String[] args){
House h = new House();
h.construct();
}
}
I am trying to learn java. Forgive me if my concepts are not clear or very wrong.
I am trying to create inheritance and polymorphism application.
I have created an array of Animals[5]. I am trying to add refrences of dog, cat to the array.
I want it to hold
Animals[0] = zooDog
I am getting error that
cannot make a static reference to the non-static
I have create AnimalstestDrivve class
package animals;
public class AnimalstestDrive {
public Animals[] myZoo = new Animals[5];
int zooCounter = 0;
public static void main(String[] args) {
//Set animals array
Dog zooDog = new Dog();
addAnimals(zooDog);
Cat zooCat = new Cat();
addAnimals(zooCat);
}
public void addAnimals(Animals a){
if ( zooCounter > 5 ){
myZoo[zooCounter] = a;
zooCounter++;
}
else
System.out.println("Zoo is full");
}
}
here is my Animals class
package animals;
public abstract class Animals {
private String Name;
private int Size; //Size on the scale 1 to 10
public void eatFood(){
System.out.println("I am eating food");
}
public void sleep(){
System.out.println("I am sleeping now");
}
abstract public void makeNoises();
}
Simple dog, cat class
package animals;
public class Dog extends Animals {
public void makeNoises(){
System.out.println("Bow! bow!");
}
}
The main method (static) attempts to call the addAnimals method, whose declaration is non-static. You need to create an instance of the class first, then call the method on this instance
AnimalstestDrive testDrive = new AnimalstestDrive();
Dog zooDog = new Dog();
testDrive.addAnimals(zooDog);
See Understanding Class Members for more information
You need to have an instance of the class AnimalstestDrive. Static means, that you don't need any instance of the class to use the class method, so if you would mark the addAnimals as static, You could use that method without creating an instance of AnimalstestDrive.
Because the method addAnimals is not static, you need to create an instance of AnimalstestDrive to use that function.
When a method is not static, it is specific to an instance of that class. For example:
AnimalstestDrive atd = new AnimalstestDrive();
atd.addAnimals(new Dog()); // this will add animals to "atd"
If a method is static, it is not specific to an instance of the class, but the class itself.
If you put this method in the class AnimalstestDrive:
public static void staticMethod() {
}
You could only access it with AnimalstestDrive.staticMethod(), not atd.staticMethod().
More info on static methods here.
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());
}
}
it may looks like a dummy question for you but I have difficulties solving this:
We have an abstract class Animal and Cat and Dog that extends it. In Animal we have a method produceSound(); that is abstract. As you can probably guess for Cat it should return "Mao" and for Dog - "Bao" or something like that. This is OK but now we must write a static method in the Animal class that returns Cat or Dog objects depending on their sound. For example: identifyAnimal("Mao") should return Cat.
Question: How to implement the identifyAnimal(String sound) method?
Here is some simple example of the hierarchy:
Animal class
public abstract class Animal {
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
// TODO
}
}
Cat class
public class Cat extends Animal{
#Override
protected String produceSound() {
return "Mao";
}
}
Dog class
public class Dog extends Animal{
#Override
protected String produceSound() {
return "Bao";
}
}
Test class
public class AnimalTest {
public static void main(String[] args) {
Animal.identifyAnimal("Bao");
}
}
In the AnimalTest class when calling the Animal.identifyAnimal("Bao"); we should get a Dog.
private static Class[] animalTypes = [Dog.class, Cat.class];
public static String identifyAnimal(String animalSound)
{
for (int i = 0; i < animalTypes.length; i++) {
Animal a = animalTypes[i].newInstance();
String s = a.produceSound();
if (animalSound.equals(s))
return animalTypes[i].getName();
}
return null;
}
So here a (terrible) way to do this. I actually twitched a little.
I don't know what language you are using, so I'm going with c++(sorry current mode) though you could replace maps with Dictionaries if we are in C#, whatever. This is a bad way to go about things, but should work(conceptually, anyway)
Again...Terrible...
public abstract class Animal {
protected abstract String produceSound();
protected static map<string, string> SoundList;
protected static bool registerSound(string sound, string type)
{
return (SoundList.insert( pair<string, string>(sound, type)))->second;//true if worked false if already there
}
protected static string identifyAnimal(string animalSound)
{
map<string,string>::iterator result = SoundList.find(sound);
if(result != SoundList.end())
return result->second;
else
return "What The Hell Is This!?";
}
}
Cat class
public class Cat extends Animal
{
Cat()
{
Animal::registerSound("Mao","Cat");
}
#Override
protected String produceSound() {
return "Mao";
}
}
abstract class Animal {
static Map<String,String> map = new HashMap<String,String>();
public Animal(String value) { map.put(produceSound(), value); }
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
System.out.println(map.get(animalSound));
}
}
class Cat extends Animal {
#Override
protected String produceSound() { return "Mao"; }
Cat(){ super("CAT"); }
}
class Dog extends Animal {
#Override
protected String produceSound() { return "Bao"; }
Dog(){ super("DOG"); }
}
class Test {
public static void main(String[] args) {
new Dog();
new Cat();
Animal.identifyAnimal("Bao");
}
}
Do a switch with the predefined sounds that you have and let each sound return a string with the name of the animal. For example "Mao" returns a string "Cat" and so on.
One more thing let ur identifyAnimal method returna string instead of void.
You could use reflection to get a list of all types that extend Animal, loop through them using Activator to create instances of each type running produceSound on each until you find the return value that matches animalSound, returning that instance. Slow, but effective if you want to avoid your Animal class being aware of what extends it.
What is the nature of the problem you are trying to solve? There is no 'right' way that is independent of the problem.
What does the consuming application need from the class Animal? What does your application need to do with the classes that it consumes? Nothing can be assumed unless these presumptions are clear.
I have an enum which is private, not to be exposed outside of the class. Is there anyway I can do a static import of that type, so that I don't have to type the enum type each time? Or is there a better way to write this? Example:
package kip.test;
import static kip.test.Test.MyEnum.*; //compile error
public class Test
{
private static enum MyEnum { DOG, CAT }
public static void main (String [] args)
{
MyEnum dog = MyEnum.DOG; //this works but I don't want to type "MyEnum"
MyEnum cat = CAT; //compile error, but this is what I want to do
}
}
You can use the no-modifier access level, i.e.
enum MyEnum { DOG, CAT }
MyEnum will not be visible to classes from other packages neither from any subclass. It is the closest form of private, yet letting you avoid explicitly referencing MyEnum.
Considering that you can access the field fully qualified, I would say that it is a bug in the compiler (or language spec) that you cannot statically import it.
I suggest that you make the enumeration package-protected.
It may (or may not) be reasonable to move some of the code into (static) methods of the enum.
If pressed, you could duplicate the static fields in the outer class.
private static final MyEnum CAT = MyEnum.CAT;
private static final MyEnum DOG = MyEnum.DOG;
Icky, but a possibility.
Or is there a better way to write this?
If your main goals are to reference the items without their qualifying enum identifier, and maintain this list privately, you could scrap the enum type altogether and use ordinary private static constants.
You could simply write your code inside the enum itself.
public enum MyEnum {
DOG, CAT;
public static void main(String[] args) {
MyEnum dog = MyEnum.DOG; // this works but I don't want to have to type
// MyEnum
MyEnum cat = CAT; // compile error, but this is what I want to do
}
}
The other place where private enums can be references without their class is in a switch statement:
private static enum MyEnum {
DOG, CAT
}
public static void main(String[] args) {
MyEnum e = null;
switch (e) {
case DOG:
case CAT:
}
}
Nope, that's pretty much what private is all about.