Java, Subclass return generics of generics - java

Does anyone can tell me how to code the return in the function "getDirectHair()" ?
I want to create a method which is like a shortcut in the Human class to directly return the good type of Hair class (below named "h.getDirectHair()") instead of use "h.getPerson().getHair()".I want to use the type <?> of Person<?> declared in Human class.
package test;
public class Test {
public static void main(String[] args) {
Human<Bob> h = new Human<Bob>();
Blond blond = h.getPerson().getHair(); // no cast needed, because Human<Bob> is blond
//how to do if I want to use directly this :
blond = (!!!) h.getDirectHair(); //need cast !! Blond or Brown ?
}
}
class Human<T extends Person<?>>{
private T person = null;
public T getPerson() {
return person;
}
public /* <?> */ Object getDirectHair(){
// => I want to return the type <?> of Person<?>
// instead of Object, how to ??
return person.getHair();
}
}
class Person<T extends Hair> {
T hair;
public Person(T hairr) {
hair = hairr;
}
public T getHair() {
return hair;
}
}
class Bob extends Person<Blond> {
public Bob(Blond bean) {
super(bean);
}
public Blond getHair() {
return super.getHair();
}
}
class Barack extends Person<Brown> {
public Barack(Brown bean) {
super(bean);
}
public Brown getHair() {
return super.getHair();
}
}
class Hair {
}
class Blond extends Hair {
}
class Brown extends Hair {
}
Many thanks and best regards,
David.

Here's how to fix the problem:
public class Test {
public static void main(String[] args) {
Human<Blond, Bob> h = new Human<Blond, Bob>();
Blond blond = h.getPerson().getHair();
blond = h.getDirectHair();
}
}
class Human<H extends Hair, T extends Person<H>>{
private T person = null;
public T getPerson() {
return person;
}
public H getDirectHair(){
return person.getHair();
}
}

Related

Factory-pattern for superclass and its subclasses

I have 3 classes which are one child of the other:
Class C ->(subclass of)-> class B ->(subclass of)-> class A.
Every class is real and I want to choose which one to instantiate by a method.
Can I use Factory-method and so factory-pattern to choose which class to create?
thank you.
Yes, the factory method is the way to go in your context. I've provided quick example how to implement it.
import java.util.Scanner;
public class FactoryMethodExample
{
public static void main(String[] args)
{
Scanner reader = new Scanner(System.in);
System.out.println("Enter a letter A, B or C: ");
String input = reader.nextLine();
Factory factory = new ConcreteFactory();
A myClass = factory.getClass(input.charAt(0));
if(myClass != null)
{
myClass.print();
}
else
{
System.out.print("Wrong input");
}
}
}
class A
{
public void print()
{
System.out.print("I'm class A");
}
}
class B extends A
{
#Override
public void print()
{
System.out.print("I'm class B");
}
}
class C extends B
{
#Override
public void print()
{
System.out.print("I'm class C");
}
}
abstract class Factory
{
public abstract A getClass(Character letter);
}
class ConcreteFactory extends Factory
{
#Override
public A getClass(Character letter)
{
if(letter.equals('A'))
{
return new A();
}
else if(letter.equals('B'))
{
return new B();
}
else if(letter.equals('C'))
{
return new C();
}
return null;
}
}
Yes you can use factory method pattern with covarient return types. Here's a sample code.
public class MazeGame {
public Maze createMaze() {
// build the maze here.
return aMaze;
}
public Room makeRoom(final int number) {
return new Room(number);
}
public Wall makeWall() {
return new Wall();
}
// ...
}
public class BombedMazeGame extends MazeGame {
#Override
public Room makeRoom(int number) {
return new RoomWithABomb(number);
}
#Override
public Wall makeWall() {
return new BombedWall();
}
}

how to "pull down" a parameter when refactor in eclipse?

before refactor:
public interface Service {
public void hello(Person p);
}
public class BlackPersonServiceImpl implements Service {
#Override
public void hello(Person p) {
//...
}
}
public class WhitePersonServiceImpl implements Service {
#Override
public void hello(Person p) {
//...
}
}
public class BeforeRefactor {
public static void main(String[] args) {
String str = args[0];
Person p = JSON.parseObject(str, Person.class);
Service service = getServiceFromSpringContainer();
service.hello(p);
}
private static Service getServiceFromSpringContainer() {
//...
return null;
}
}
after refactor:
public interface Service {
public void hello(String str);
}
public class WhitePersonServiceImpl implements Service {
#Override
public void hello(String str) {
Person person = JSON.parseObject(str, Person.class);
//do something to person...
//...
}
}
public class AfterRefactor {
public static void main(String[] args) {
String str = args[0];
Service service = getServiceFromSpringContainer();
service.hello(str);
}
private static Service getServiceFromSpringContainer() {
//...
return null;
}
}
That's what I want(I think "pull down" is not the "right" word to describe it...).
I tried "introduce parameter object" in eclipse, and it does not work.
There are many implementations of "Service". I dont want to change them one by one.
Is there a good way to solve this problem?
Thanks!
You can do it somewhat for a single class and a single method (although it's akward and a succession of small refactoring steps), but not across several types at the same time.

Create Enum with list of the same object

I would like to create an enum containing one attribut, a list of objects extending the same interface or the same abstract class.
The objective is to have a loop on each list of my enum to call methods dynamically.
public interface Regles {
void verifier();
}
public class Regle01 implements Regles {
#Override
public void verifier() {
}
}
public class Regle02 implements Regles {
#Override
public void verifier() {
}
}
public enum ListRegles {
ENUM1(Arrays.asList(new Regle01(), new Regle02())),
ENUM2(Arrays.asList(new Regle01()))
private List<Regles> regles = new ArrayList<Regles>();
ListRegles(List<Regles> r) {
regles = r;
}
}
how can i do this please ?
enum:
public enum ListRegles {
ENUM1(new Regle01(),new Regle02()),
ENUM2(new Regle01());
private List<Regles> regles ;
ListRegles(Regles... regles) {
this.regles = new ArrayList<>(Arrays.asList(regles));
}
public void verify() {
for (Regles regle : regles) {
regle.verifier();
}
}
}
Will call verifier for Regle01 and Regle02
ListRegles.ENUM1.verify();

How to apply Simple Factory Pattern Java

I am trying ot understand how to apply a the simple factory pattern to an assigment I have but I do not understand how to do it.
This is the request: Apply the Simple Factory pattern that creates the appropriate Strategy object.
Remember, this is a Simple Factory pattern. Draw the UML diagram of the new
design.
We already implemented the strategy pattern but I do not understand how to apply the simple factory pattern to the code. I understand that the simple factory pattern is supposed to provide encapsulation for the creation of the object but I do not see how the examples I have found show how to apply to this. Any help would be appreciated.
EDIT: Updated code
EDIT: Changed code to make use of polymorphism
package Client;
import domain.Loan;
import factory.StrategyFactory;
import strategy.ComplexLoan;
import strategy.ICapitalStrategy;
public class Client {
public static void main(String[] args){
Loan complexLoan = new Loan(2.2, 2, 3.3, 4.4, 5, 6, 7, StrategyFactory.getComplexStrategy());
System.out.print("hello");
}
}
package factory;
import strategy.ComplexLoan;
import strategy.ICapitalStrategy;
import strategy.RevolvingLoan;
import strategy.TermLoan;
public class StrategyFactory {
/*
public static ICapitalStrategy getStrategy(String type) {
if (type.equals("Complex")){
return new ComplexLoan();
}
else if (type.equals("Revolving")){
return new RevolvingLoan();
}
else if (type.equals("Term")){
return new TermLoan();
}
return null;
}
*/
public static ICapitalStrategy getComplexStrategy() {
return new ComplexLoan();
}
public static ICapitalStrategy getRevolvingStrategy() {
return new RevolvingLoan();
}
public static ICapitalStrategy getTermStrategy() {
return new TermLoan();
}
}
package domain;
import strategy.ICapitalStrategy;
public class Loan {
private ICapitalStrategy strategy;
double commitment;
int duration;
double riskFactor;
double unusedPercentage;
int outstandingRiskAmount;
int unusedRiskAmount;
double unusedRiskFactor;
double capital;
public Loan(double commit, int dura, double rskFact, double unusedPer,
int outStandRskAmt, int unusedRskAmt, double unusedRskFac,
ICapitalStrategy strat) {
this.commitment = commit;
this.duration = dura;
this.riskFactor = rskFact;
this.outstandingRiskAmount = outStandRskAmt;
this.unusedRiskAmount = unusedRskAmt;
this.unusedRiskFactor = unusedRskFac;
this.strategy = strat;
}
public double CalculateCapital() {
return strategy.CapitalLoan(this);
}
public double getCommitment() {
return commitment;
}
public void setCommitment(double c) {
commitment = c;
}
public int getDuration() {
return duration;
}
public void setDuration(int dur) {
duration = dur;
}
public double getRiskFactor() {
return riskFactor;
}
public void setRiskFactor(double rskFac) {
riskFactor = rskFac;
}
public double getUnusedPercentage() {
return unusedPercentage;
}
public void setUnusedPercentage(double unusedPercent) {
unusedPercentage = unusedPercent;
}
public double getOutstandingRiskAmount() {
return outstandingRiskAmount;
}
public void setOutstandingRiskAmount(int outStandingRskAmt) {
outstandingRiskAmount = outStandingRskAmt;
}
public double getUnusedRiskAmount() {
return unusedRiskAmount;
}
public void setUnusedRiskAmount(int UnusedRskAmt) {
unusedRiskAmount = UnusedRskAmt;
}
public double getUnusedRiskFactor() {
return unusedRiskFactor;
}
public void setUnusedRiskFactor(double unusedRskFac) {
unusedRiskFactor = unusedRskFac;
}
public Loan(ICapitalStrategy strategy) {
this.strategy = strategy;
}
/*public double executeStrategy() {
return this.strategy.CapitalLoan(this);
}
*/
}
package strategy;
import domain.Loan;
public class ComplexLoan implements ICapitalStrategy {
#Override
public double CapitalLoan(Loan l) {
return ((l.getOutstandingRiskAmount() * l.getDuration() * l.getRiskFactor()) + (l.getUnusedRiskAmount()
* l.getDuration() * l.getUnusedRiskFactor() ));
}
}
package strategy;
import domain.Loan;
public interface ICapitalStrategy {
public double CapitalLoan(Loan l);
}
package strategy;
import domain.Loan;
public class RevolvingLoan implements ICapitalStrategy {
#Override
public double CapitalLoan(Loan l) {
return (l.getCommitment() * l.getUnusedPercentage() * l.getDuration() *l.getRiskFactor());
}
}
package strategy;
import domain.Loan;
public class TermLoan implements ICapitalStrategy {
public TermLoan() {
}
public double CapitalLoan(Loan l) {
return (l.getCommitment() * l.getDuration() * l.getRiskFactor());
}
}
Here's a likely helpful bit about Simple Factory Pattern[1]:
The simple factory isn't actually a pattern; it's more of a design principle. The simple factory encapsulates the object creation code, but keeps control over how the object is created. Simple factories are often designed as a class with a static method (aka static factory) that returns the object requested.
Here's an example, not suited directly to your example in order to make you think a bit hard for your homework :)
interface Foo{
double calculateStuff();
}
class MyClass implements Foo{
#Override
public double calculateStuff(){
//logic goes here
}
}
class MyFactory {
public static double getCalculatedStuff(){
return new MyClass().calculateStuff();
}
}
class RunCode {
public static void main(String[] args){
double stuff = MyFactory.getCalculatedStuff();
}
}
[1] - Learning Design Patterns - Factory Pattern
EDIT:
class LoanFactory{
public static double getComplexLoan(Loan l){
return new ComplexLoan().CapitalLoan(l);
}
}
another way (which has its uses, but in this case I prefer the method above):
class ComplexLoan implements ICapitalStrategy{
private ComplexLoan(){
}
public static double getLoan(Loan l){
return new ComplexLoan().CapitalLoan(l);
}
}
or this option that explicitly displays polymorphism:
class LoanFactory{
public static ICapitalStrategy getComplexLoan(){
return new ComplexLoan();
}
}
One other thing that is important to note: convention says method names should start with a lowercase letter, so your CapitalLoan() would be capitalLoan().
Also, there's no need to prefix your interfaces with an I, so your ICapitalStrategy would become CapitalStrategy.
In the following example. The "Document" is abstract class and "html" document. "MyDocument" and "pdf" are concrete class. As long as you provide parameter with valid string, you will get the corresponding concrete class. For example if you put "pdf" as a parameter, you will get pdf document. Document type is all you need to accept whatever type of documents you want to create.
public Document CreateDocument(String type){
if (type.isEqual("html"))
return new HtmlDocument();
if (type.isEqual("proprietary"))
return new MyDocument();
if (type.isEqual("pdf"))
return new PdfDocument ();
}
There is a better documented article thread in
Examples of GoF Design Patterns in Java's core libraries
public interface PaymentMethod {
public void makePayment();
}
class CreditCard implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through credit card...");
}
}
class NetBanking implements PaymentMethod {
public void makePayment() {
System.out.println("Payment through net banking...");
}
}
public class PaymentMethodFactory {
public static PaymentMethod getPaymentMethod(String method) {
if ("creditcard".equalsIgnoreCase(method)) {
return new CreditCard();
} else if ("netbanking".equalsIgnoreCase(method)) {
return new NetBanking();
} else {
throw new IllegalArgumentException("Payment method not supported!");
}
}
}
public class SimpleFactoryTest {
public static void main(String[] args) {
PaymentMethodFactory factory = new PaymentMethodFactory();
PaymentMethod paymentMethod = factory.getPaymentMethod("creditcard");
paymentMethod.makePayment();
}
}

How to use static method to construct in snakeyaml?

I have a class with a private constructor and a static method that returns instances, like below:
public class OptionsBean {
public static final OPTION1 = new OptionsBean(0, "COLOR");
public static final OPTION2 = new OptionsBean(1, "SIZE");
private OptionsBean(int id, String name) { ... }
public static OptionsBean valueOf(String name) {
if (name.equals("COLOR")) {
return OPTION1;
} else {
return OPTION2;
}
}
}
The root class would look something like this:
public class Root {
...
public OptionsBean getOptions() { ... }
public void setOptions(OptionsBean value} { ... }
...
}
And I'd like my YAML to look like this:
name: Colored Box
options: COLOR
height: 100
width: 100
I know I can use tags to get something like what I want, but I'd rather not have to use an explicit tag.
I seemed to have solved my own problem, although I don't know how "correct" it is:
private static class MyConstructor extends Constructor {
public MyConstructor(Class<? extends Object> theRoot) {
super(theRoot);
this.yamlClassConstructors.put(NodeId.scalar, new ConstructCustom());
}
private class ConstructCustom extends ConstructScalar {
#Override
public Object construct(Node node) {
if (node.getType().equals(OptionsBean.getClass())) {
return OptionsBean.valueOf(node.getValue());
} else {
return super.construct(node);
}
}
}
}

Categories