public class Player implements Comparable<Player> {
//Fields
private Name name;
private Rollable rollable;
//Constructors
public Player() {
name = new Name();
rollable = new Rollable();
}
public Player(Name name) {
this.name = name;
rollable = new Rollable();
}
public Player(Name name, Rollable rollable) {
this.name = name;
this.rollable = rollable;
}
Hello, for my constructors where i have put rollable = new Rollable(); I am getting an error which states that it Cannot instantiate the type rollable.
Below i have added the JUnit test and i will also add the code for the Rollable class
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.
getName());
assertTrue("Player's rollable field should be initialised with an. implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
#Test
public void testCustomConstructor1arg() {
Name n = new Name("Joe", "Bloggs");
Player p = new Player(n);
assertSame("Player's name field should be initialised with and return the same object received by the constructor", n, p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
Now below is the JUnit test for the default constructor whcih is also giving me the failure of Players rollable field should be initialised with an implementing instance of the Rollable interface, however, all of my other JUnit tests are passing.
#Test
public void testDefaultConstructor() {
Player p = new Player();
assertEquals("Name field should be initialised with a default Name object ", new Name(), p.getName());
assertTrue("Player's rollable field should be initialised with an implementing instance of the Rollable interface", p.getRollable() instanceof Rollable);
}
The code for my Rollable class is as below;
public interface Rollable {
public void roll();
public int getScore();
}
The methods for my rollable code are as below;
//Methods
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public Rollable getRollable() {
return rollable;
}
public void rollDice() {
rollable.roll();
}
public int getDiceScore() {
return rollable.getScore();
}
All help will be appreciated as i am struggling with the failures, thank you.
Your getRollable() method is:
public Rollable getRollable() {
return rollable;
}
So, if you call that from a constructor, for example:
public Player() {
name = new Name();
rollable = getRollable();
}
then rollable will be assigned the value of rollable, which is by default null.
As such, when you call getRollable() again in the test, you get back the value you assigned to the field - null - and by definition - null instanceof Rollable is false.
Instead, you need to create a new instance of Rollable, for example:
rollable = new Rollable();
(Don't know if it is directly instantiable. You've not provided the declaration of the Rollable class).
Your Rollable is an interface, and in Java you can only create instances of non-abstract classes.
So you need to write at least one class that implements Rollable. Of this class, you can create instances.
Why is that so?
Have a look at e.g. the Comparable interface (serving me as an analogon to your Rollable). Comparable denotes classes that support some kind of greater / equal / less than comparison, by requiring the class to have a method named compareTo(). If you were to instantiate a Comparable, what would you expect to be the result? A String, a Long, a Double or what? And the same applies to your Rollable.
An interface defines some requirements that implementing classes must fulfill, but they don't denote classes themselves, so you can't create (direct) instances of interfaces.
Related
I have an enum and on creating an instantion of a class, I want to create object of the class from Enum. Tbh I dont think so that I explained it properly so I will just show it.
public enum TypCiala{
GWIAZDA,
PLANETA,
KSIEZYC,
ASTEROIDA,
KOMETA
}
public Ciało(String nazwa, double okresOrbitowania, TypCiala typ) {
this.nazwa = nazwa;
this.okresOrbitowania = okresOrbitowania;
this.ksiezyce = new HashSet<>();
this.typ = typ;
}
while creating an instantion in Main method I want to create subclass of the typ(my enum) parameter
Ciało stack = new Ciało("Earth", 333, Ciało.TypCiala.PLANETA);
I have made the subclassed for Enum, but I have no idea how to implement them, so while creating the class there gonna be made subclass of this object
public class Planeta extends Ciało{
public Planeta(String nazwa, double okresOrbitowania, TypCiala typ) {
super(nazwa, okresOrbitowania, typ);
}
}
Is it correct to use java.util.function.Function to implement Factory Design Pattern
In the following example, I've used Function reference to instantiated a Person type object.
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Function<String , Person> myFunc = (String s) -> new Person(s);
Person p = myFunc.apply("John");
System.out.println(p.getName());
}
}
class Person{
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
The factory design pattern is used to hide implementation logic behind an object factory and its power is to use inheritance to achieve this. Say you would have more than one type of person, e.g. a SmartPerson and a DumbPerson (implementing the same Person base class). One could ask the factory to create either a smart or a dumb person without ever knowing about the implementation differences, since all it ever returns is a Person object.
You can instantiate a person with a function referring to the constructor, but this pattern is about the location of the object creation, allowing you to hide certain implementation logic.
This hiding of logic behind a factory saves you a lot of time in the future where different classes may use the factory to create persons, because a change to the way you create a person would only require you to modify the creation methods in the factory and does not affect each individual class using the factory.
#Test
public void testSimpleFactory() {
PersonFactory personFactory = new PersonFactory();
Person person = personFactory.createPerson("dumb");
person.doMath(); // prints 1 + 1 = 3
}
public class PersonFactory {
public Person createPerson(String characteristic) {
switch (characteristic) {
case "smart":
return new SmartPerson();
case "dumb":
return new DumbPerson();
default:
return null;
}
}
}
public interface Person {
void doMath();
}
public class SmartPerson implements Person {
#Override
public void doMath() {
System.out.println("1 + 1 = 2");
}
}
public class DumbPerson implements Person {
#Override
public void doMath() {
System.out.println("1 + 1 = 3");
}
}
Let's say we have a class with the following method:
public class Entry {
private String name;
public static Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
This class may be subclassed (e.g. SubEntry), and the logic behind "getOrCreate" does not change. But the subclasses should not return a new object of the type Entry, but of the type of the respective subclass (e.g. return SubEntry(name))
How can I realize this without reimplementing the method getOrCreate for every subclass of Entry? Is there a term for this kind of technique?
Subclassing Entry does not affect the getOrCreate method because static methods are not part of a class instance; they do not logically belong in any class.
If you instead move getOrCreate into a non-static Factory class, you can use some Generics magic to determine the returned type:
public class Entry {
private String name;
}
abstract class AbstractEntryFactory<T extends Entry>
public abstract T getOrCreate(String name);
}
public class EntryFactory extends AbstractEntryFactory<Entry>
#Override
public Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
public class SubEntryFactory extends AbstractEntryFactory<SubEntry>
#Override
public SubEntry getOrCreate(String name) {
// ...
return new SubEntry(name);
}
}
Actually calling the getOrCreate would look different from what it would look like with your code. Instead of this:
Entry myEntry = Entry.getOrCreate("my name");
It would instead look like this:
Entry myEntry = new EntryFactory().getOrCreate("my name");
Or this:
SubEntry myEntry = new SubEntryFactory().getOrCreate("my name");
Assuming you wanted to be able to call Entry.getOrCreate() to create a type of SubEntry, you'll have to pass along some extra information. The reason is that the getOrCreate() method is not inherited by SubEntry, since it is a static method. So if you want to call it the way I mentioned, you'll have to pass along the class name that you want to create. In the code below there are no checks to validate that Class clazz is an Entry or a subtype, but this gives you a start.
import java.lang.reflect.Constructor;
public class TestClass {
public static void main(String[] args) {
Entry entry = (Entry)Entry.getOrCreate("entry", Entry.class);
SubEntry subEntry = (SubEntry)SubEntry.getOrCreate("subEntry", SubEntry.class);
System.out.println("entry class: " + entry.getClass().getName());
System.out.println("subEntry class: " + subEntry.getClass().getName());
}
}
class Entry {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Object getOrCreate(String name, Class clazz) {
// If a constructor is created that takes a String, such as "public Entry(String name)",
// then each sub class will need to implement that method. Instead I used a getter and
// setter for the name attribute.
try {
Entry entry = (Entry)clazz.newInstance();
entry.setName(name);
return entry;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class SubEntry extends Entry {
}
The end result is this output:
entry class: Entry
subEntry class: SubEntry
There are two questions you are asking:
How do I do this?
What is this technique called?
The second one is much more important than the first.
It seems to me like what you are trying to achieve is similar to the concept of cloning (link) or virtual constructor. But you would like this to be a static method, which raises the question as to why? Since a static method is tied to a certain class, not an instance, you should call it through that class in which case you may just as well explicitly be calling new. But having searched for "retrive class in static context" I would say it is not possible to do exactly what you wrote in the question.
If you convert the static method to a normal method, this can be done by using reflection:
class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
public Entry() {
this.name = null;
}
public Entry getOrCreate(String name) {
try {
return getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
return new Entry(name);
}
}
}
class BetterEntry extends Entry {
public BetterEntry(String name) {
super(name);
}
public BetterEntry() {
super();
}
}
You would then be calling the function from an instance, like so:
Entry a = new Entry().getOrCreate("First");
Entry b = new BetterEntry().getOrCreate("Second");
Entry c = b.getOrCreate("Third");
The dynamic types of a, b, c are Entry, BetterEntry and BetterEntry. You could leave out the default constructors, but I added them to make calling getOrCreate feel more like a static method.
If you really want the method to be static, the simplest way would be to just reimplement this function in every subclass.
For a particular program, I essentially have an abstract superclass with several different subclasses. However, I'm having trouble with field shadowing as illustrated below.
abstract class Super {
String name;
String getName() {
return name;
}
}
Now I create subclasses that each have their own "name".
class Sub extends Super {
name = "Subclass";
}
However, creating instances of the subclass, and then calling the inherited method getName() will yield null due to field shadowing.
Is there an easy way to avoid this problem, and to allow subclasses to each have a unique field that can be accessed by an inherited method?
Make the field visible in the child class and initialize it in the subclass constructor or in a subclass instance initializer.
You might try this mechanism (bonus left to reader, extend code to get the name of the class directly). The code use the Abstract classes constructor to set the name. You could also define a setName function in the Super class and use that.
Super class (abstract)
package stackShadow;
public abstract class Super {
String name;
public Super(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Shadow1 class first subclass
package stackShadow;
public class Shadow1 extends Super {
public Shadow1() {
super("Shadow1");
}
}
Shadow2 class second subclass
package stackShadow;
public class Shadow2 extends Super {
public Shadow2() {
super("Shadow2");
}
}
Test class to test getName
package stackShadow;
public class Test {
public static void main(String[] args) {
Shadow1 one = new Shadow1();
Shadow2 two = new Shadow2();
System.out.println("Name for one is: " + one.getName());
System.out.println("Name for two is: " + two.getName());
}
}
So let say I have such prototyping:
private static Hashtable<String, Furniture> map =
new Hashtable<String, Furniture>();
public My_product() {
loadCache();
}
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
return (Furniture) cachedproduct.clone();
}
private static void loadCache() {
Sub_product1 pr1 = new Sub_product1(null);
map.put("pr1", pr1);
Sub_product2 pr2 = new Sub_product2(null);
map.put("pr2", pr2);
}
So when I make an instance of an object, I don't know what value will be entered after cloning it (creating object using cloning). So I chosen null value for object instance. But when I clone it then I know what value needs to be assigned for that object. So how could I specify while cloning to put some value instead of null one from object instance?
As you can see in method createProduct method, there is argument called name. I would like that name to be used in cloned object, but how could I do that?
Can you use setter methods?
public My_Product createProduct(String type, String name) {
Furniture cachedproduct = map.get(type);
Furniture clonedProduct = (Furniture) cachedproduct.clone();
clonedProduct.setType(type);
clonedProduct.setName(name);
return clonedProduct;
}
However, I'm still not clear on the whole idea of this cloning of cached objects from the map. Is your product instantiation very expensive? What's the trick?
You cannot pass arguments through the Java built-in clone mechanism. You could provide a setter on the Furniture class to change the name after it has been cloned.
Note that cloning in Java is generally considered broken. It is a brittle way to create objects. Generally you are better of using the factory pattern, e.g. something like:
interface FurnitureBuilder {
Furniture build(String name);
}
class SubProduct1Builder implements FurnitureBuilder {
public Furniture build(String name) { return new SubProduct1(name); }
}
class MyFurnitureFactory {
private final Map<String, FurnitureBuilder> builderByType = ...
// initialization omitted
public Furniture create(String type, String name) {
return builderByType.get(type).build(name); // null check omitted!
}
}