Page 1 of 2

HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 09, 2019 6:09 pm
by OCAJO1
Two questions:

Question One:
System.out.println(r.getChannel()); //should print 0
Shouldn't the pointer in the above line from exercise 2 change to

System.out.println(t.getChannel()); //should print 0

If not, please drop a hint or two, as for what is this exercise is aiming to accomplish.

Question Two:

Lets assume that the above pointer issue was just a typo. If so, which one of these two solutions would be a good code for exercise 2, overloaded methods or use of instanceof and casting to create a single method?

Code: Select all

static void reset (Object input){
        if (input instanceof TV)
          ((TV)input).setChannel(0);
        else
          ((Radio)input).setFrequency(0.0); 
}
or

Code: Select all

static void reset (TV input){    
        input.setChannel(0);
    }
    
static void reset (Radio input) {
        input.setFrequency(0.0);
}
Here are Radio & TV classes for reference

Code: Select all

class Radio{
    private double frequency = 1.1; //insert appropriate getter and setter
    
    public void setFrequency (double f){
        this.frequency = f;
    }
    
    public double getFrequency(){
        return frequency;
    }
}    

class TV{
    private int channel = 5; //insert appropriate getter and setter
    
    public void setChannel(int c){
        this.channel = c;
    }
    
    public int getChannel(){
        return channel;
    }
}
Here is the TestClass' main() for reference

Code: Select all

public static void main(String[] args){
       
       /* This segment is for Exercise 1 and not relevant to this set of questions 
        Document d = new PdfDocument();
        d.setType("pdf");
        System.out.println(d.getType()); //should print "pdf"
        */
        
        TV t = new TV();
        Radio r = new Radio();
        reset(t);
        reset(r);
        System.out.println(r.getFrequency()); //should print 0.0
        System.out.println(t.getChannel()); //should print 0
    }
Thanks

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 09, 2019 9:37 pm
by admin
1. Yes, it should be t.getChannel.

2. Either one of the approaches is fine. I would use the instanceof approach because it would be easier to change later. But one could go for overloaded methods also because they look cleaner.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 10, 2019 12:41 pm
by OCAJO1
3. You are expected to reset several electronic devices in future. Refactor the code given above
such that TestClass's reset method is able to reset any new device without requiring any
change in the method code.
Incorporating the requirements of exercise 3, would you agree that it would be better coding to have overloaded reset method and introduce the following code?

Code: Select all

static void device (Object input){

        if (input instanceof TV)
          reset((TV)input);
        else
          reset((Radio)input); 
}
and of course changing TestClass' main() to call device(r) and device(t) rather than reset(r) and reset(t)?

Thanks

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 10, 2019 1:06 pm
by admin
No, your device method doesn't satify the requirement.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 10, 2019 6:14 pm
by OCAJO1
Would introduction of the Electronics class and changes the TestClass' main() provide sufficient refactoring for exercise 3's requirements? If still not enough, or cleaner way of doing it - I appreciate a hint or 2. Thanks

Code: Select all

class Electronics{
    
    static void device (String input){

        TestClass tc = new TestClass();
        
        if (input.equals("TV")){
            TV tv = new TV();
            tc.reset(tv);
            System.out.println(tv.getChannel());
        
        }else if (input.equals("Radio")){
            Radio rd = new Radio();
            tc.reset(rd); 
            System.out.println(rd.getFrequency());
        }  
    }
    
}

Code: Select all

class TestClass{
    
    /* This approach works just as well in exercise 2.
    
    static void reset (Object input){
        if (input instanceof TV)
          ((TV)input).setChannel(0);
        else
          ((Radio)input).setFrequency(0.0); 
    }
    */
    
    void reset (TV input){    
        input.setChannel(0);
    }
    
    void reset (Radio input) {
        input.setFrequency(0.0);
    }
    
    public static void main(String[] args) throws IOException {
        
        /* This segment is for Exercise 1 and not relevant to this set of questions
        Document d = new PdfDocument();
        d.setType("pdf");
        System.out.println(d.getType()+"\n"); //should print "pdf"
        */
        
        //TV t = new TV(); //used in exercise 2
        //Radio r = new Radio(); //used in exercise 2
        //reset(t); used in exercise 2
        //reset(r); used in exercise 2
        
        Electronics.device("TV"); // used in exercise 3
        Electronics.device("Radio"); // used in exercise 3
        
        //used in excercise 2
        //System.out.println(r.getFrequency()); //should print 0.0
        //System.out.println(t.getChannel()+"\n"); //should print 0
        }
}


Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 10, 2019 9:05 pm
by admin
You are missing the point. You have to use polymorphism/overrides. Create a common base class for TV and Radio and put an abstract reset method there. From main, just invoke reset on that common base class reference.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Thu Apr 11, 2019 1:57 pm
by OCAJO1
Part 1. Oh ok I get it, move on from overloading to overriding methods.

Part 2.
From main, just invoke reset on that common base class reference.
I'm missing something here. The common base class will be an abstract class in order to support the abstract reset method. What do you mean by invoke reset on that common base class reference?

However, I've made the following modifications to the code implementing method overrides. If removing the parameters violates the exercise requirements, then I am counting on further clarification of part 2 of your comments to point me to the right direction.

Code: Select all

class TestClass{
  
    public static void main(String[] args) 
        
        //Excercise 3
        TV t = new TV();
        Radio r = new Radio();
        r.reset(); 
        t.reset();
        
        //used in excercise 2 & 3
        System.out.println(r.getFrequency()); //should print 0.0
        System.out.println(t.getChannel()+"\n"); //should print 0
      }
}

abstract class Electronics{
    
    abstract void reset();
    
}

class Radio extends Electronics{
    private double frequency = 1.1; //insert appropriate getter and setter
    
    public void setFrequency (double f){
        this.frequency = f;
    }
    
    public double getFrequency(){
        return frequency;
    }
    
    @Override
    public void reset () {    
        setFrequency(0.0);
    }
}    

class TV extends Electronics{
    private int channel = 5; //insert appropriate getter and setter
    
    public void setChannel(int c){
        this.channel = c;
    }
    
    public int getChannel(){
        return channel;
    }
    
    @Override
    void reset (){
        setChannel(0);
    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Thu Apr 11, 2019 9:52 pm
by admin
In TestClass:
static void reset(Electronics e){
e.reset();
}

You can pass any new device to this method.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Fri Apr 12, 2019 1:39 pm
by OCAJO1
Wow, is like finding the missing link to abstract classes :o

I tested it on an interface below, it works just as well.

Thanks a bunch :thumbup:

Code: Select all

interface Vehicle {
    
    void run ();
}

class Car implements Vehicle{
    private double speed;
    
    public void setSpeed (double f){
        this.speed = f;
    }
    
    public double getSpeed(){
        return speed;
    }
    
    @Override
    public void run () {    
        setSpeed(40.0);
    }
}


public class Test {
    
    static void run( Vehicle v){
       v.run();
    }


    public static void main(String[] args) {
        

        Car c = new Car();
        
        run(c); 
        
        System.out.println(c.getSpeed()); 

        
    }
    
}
Also the following are solutions to exercises 3-7. I appreciate a look see to make sure they satisfy the requirements, and any possible suggestions you might have to streamline any of them. Thanks

Code: Select all

package ocaex11;
import java.io.*;


class TestClass{
    
    static void reset(Electronics e){
       e.reset();
    }
    
    static void printCalories(Nutritionist n){
        n.printCalories();
    }
    
    public static void main(String[] args){       
        
        //Excercise 2 & 3
        TV t = new TV();
        Radio r = new Radio();
        
        //used in exercise 2 & 3
        reset(t);
        reset(r); 
        
        //used in excercise 2 & 3
        System.out.println(r.getFrequency()); //should print 0.0
        System.out.println(t.getChannel()); //should print 0
        
        System.out.println();
        
        //Excercise 4 & 5
        PumpkinPie pp = new PumpkinPie();
        pp.makePie(); //used in 4
        printCalories(pp); //used in 5
        
        ApplePie ap = new ApplePie();
        ap.makePie(); //used in 4
        printCalories(ap); // used in 5     
    }
}


abstract class Electronics{
    
    abstract void reset();
    
}

class Radio extends Electronics{
    private double frequency = 1.1; //insert appropriate getter and setter
    
    public void setFrequency (double f){
        this.frequency = f;
    }
    
    public double getFrequency(){
        return frequency;
    }
    
    @Override
    public void reset () {    
        setFrequency(0.0);
    }
}    

class TV extends Electronics{
    private int channel = 5; //insert appropriate getter and setter
    
    public void setChannel(int c){
        this.channel = c;
    }
    
    public int getChannel(){
        return channel;
    }
    
    @Override
    void reset (){
        setChannel(0);
    }
}

abstract class Nutritionist {
    
    abstract void printCalories ();            
}

class Pie extends Nutritionist {
    
    public void makePie(){
        System.out.println("Making pie.");
    }
    
    public static int getCalories(){
        return 100;
    }
    
    @Override
    void printCalories () {
        System.out.println("Average pie calories: "+getCalories()+"\n");
    }
}

class PumpkinPie extends Pie {
    
    PumpkinPie (){
        super.makePie();
    }
    
    @Override
    public void makePie(){
        System.out.println("Making pumpkin pie.");
    } 
    
    public static int getCalories(){
        return 200;
    }
    
    @Override
    void printCalories () {
        System.out.println("Pumkin pie calories: "+getCalories()+"\n");
    }
}

class ApplePie extends Pie {
    
    ApplePie(){
        super.makePie();
    }
    
    @Override
    public void makePie(){
        System.out.println("Making apple pie.");
    }
    
    public static int getCalories(){
        return 300;
    }
    
    @Override
    void printCalories () {
        System.out.println("Apple pie calories: "+getCalories()+"\n");
    }
}

//Exercise 6 & 7

abstract class Transformer {
    abstract String transform (String Data) throws IOException;
}

class XMLTransformer extends Transformer {
    
    @Override
    public String transform(String Data){
        return "xmldata.";
    }
}

class NetworkTransformer extends Transformer {
    
    @Override
    public String transform (String Data) throws IOException {
        return "data from network.";
    }
}

class TransformerFactory {
    
    static public String getTransformer(Transformer t) throws IOException{
        return t.transform("transfer method?");
    }
    
    public static void main (String[] ...args) throws IOException{
        
        XMLTransformer  xt = new XMLTransformer();
        System.out.println(getTransformer(xt));
        
        NetworkTransformer nt = new NetworkTransformer();
        System.out.println(getTransformer(nt));
        
        
    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Fri Apr 12, 2019 10:18 pm
by admin
>>Wow, is like finding the missing link to abstract classes :o

Will try to improve the chapter text to make this point clearer.


If your class name is TransformerFactory and its method name is getTransformer, why it that method not returning a Transformer?

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Sat Apr 13, 2019 2:15 pm
by OCAJO1
I hope you don't make it too obvious though. I learned more pin pointing this missing link than if it were just a section in the book :)

I was wondering that return t.transform("transfer method?"); somehow was wasting the parameter, but wasn't sure. I'll look at it more carefully!

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Mon Apr 15, 2019 1:53 pm
by OCAJO1
I think this solution is a lot cleaner than the last one.

Question: Unless my code is still not addressing the exercise requirements (not sure what else can I do to it?)- since it is returning a hardcoded string, what is the point of transform method having a String parameter?

Code: Select all

//Exercise 6 & 7

abstract class Transformer {
    abstract String transform (String Data) throws IOException;
}

class XMLTransformer extends Transformer {
    
    @Override
    public String transform(String Data){
        return "xmldata.";
    }
}

class NetworkTransformer extends Transformer {
    
    @Override
    public String transform (String Data) throws IOException {
        return "data from network.";
    }
}

class TransformerFactory {
    
    private Transformer t;

    public void setTransformer(Transformer st){
        this.t = st;
    }
    
    public String getTransformer() throws IOException{
        return t.transform("");
    }
       
    
    public static void main (String[] ...args) throws IOException{
        
        TransformerFactory tf = new TransformerFactory();
        
        XMLTransformer  xt = new XMLTransformer();
        tf.setTransformer(xt);
        System.out.println(tf.getTransformer());
        
        NetworkTransformer nt = new NetworkTransformer();
        tf.setTransformer(nt);    
        System.out.println(tf.getTransformer());
        
        
    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Mon Apr 15, 2019 9:59 pm
by admin
Yes, this looks better.

TransformerFactory should not have setTransformer. It is a factory, so it should create its own Transformer and return that transformer through getTransformer.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 16, 2019 12:23 pm
by OCAJO1
By making the transformers, I gather you mean to use the two transformer classes extending abstract class Transformer to make the transformers. If so, I believe the code below does this.

However, since the code still not making use of transform method's String parameter, I have to wonder if the approach is what the exercise is looking for?

If the above question is even relevant - If the return from the overridden transform methods were not hardcoded string, some code like this code segment in getTransformer method could make use of the transform method's String parameter.

Code: Select all

        private String data;
        ....
        
        if (t instanceof XMLTransformer)
            data = "xmldata";
        else if (t instanceof NetworkTransformer)
            data = "data from network";
        
        return t.transform(data);

Code: Select all

class TransformerFactory {
    
    private Transformer t;
    
    public String getTransformer(Transformer x) throws IOException{
        
        this.t = x;
        return t.transform("");
    }
       
    
    public static void main (String[] ...args) throws IOException{
        
        TransformerFactory tf = new TransformerFactory();
        
        XMLTransformer  xt = new XMLTransformer();
        System.out.println(tf.getTransformer(xt));
        
        NetworkTransformer nt = new NetworkTransformer();  
        System.out.println(tf.getTransformer(nt));
        
        
    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 16, 2019 6:28 pm
by admin
Please google Factory pattern to see what I meant.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 16, 2019 7:31 pm
by OCAJO1
Oh, so is not just a clever wording in a sentence! I'll rewrite the factory part.

By the way, considering when I googled it, how many different books out there have details about Factory pattern in Java, I think this book is missing at least some sort of outline, if not a subsection, about this subject.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Tue Apr 16, 2019 7:57 pm
by admin
Factory pattern is not required for OCAJP at all. But because you used the word factory in TransformerFactory and this discussion was veering a bit towards that, I suggested you to read about it. As you found out, there are tons of articles about it. No point in me reinventing the wheel here :)

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 17, 2019 6:47 pm
by OCAJO1
I came across a study that suggested that using enums is most maintainable way to approach creating Factory pattern solutions. So I looked into a couple of examples and came up with this solution for exercise 7.

Two bothersome points about this solution:

1. I had to call the method (overridable one to boot!) transform() from the constructors.
2. I still don't have a solution that utilizes the String parameter of the transform method in the exercise 7!

Questions:

1. Without going through Dependency Injection Frameworks, is there a way I can change the flow so that the call to transform method comes out of the constructors?

2. I wonder if the solution to the first question can be accomplished by the answer to the second bothersome point?

So, I would appreciate a few lines of code hinting to a possible solution. After all, I eventually have to get on with this chapter :) Thanks

Code: Select all

import java.io.IOException;

enum TransformerType {
        
    XML, NETWORK
}

abstract class Transformer {
    
    final private TransformerType tType;
    
    public Transformer(TransformerType tType) {
        this.tType = tType;
    }
    
    public TransformerType getTransformerType() {
        return tType;
    }
    
    abstract void transform () throws IOException;
}

class XMLTransformer extends Transformer {
    
    XMLTransformer() {
        super(TransformerType.XML);
        transform();
    }
    
    @Override
    public void transform(){
        System.out.println("xmldata.");
    }
}

class NetworkTransformer extends Transformer {
    
    NetworkTransformer() throws IOException{
       super(TransformerType.NETWORK);
       transform();
    }    
    
    @Override
    public void transform () throws IOException {
        System.out.println("data from network.");
    }
}

class TransformerFactory {
    
    public static Transformer getTransformer(TransformerType x) throws IOException{
        
        Transformer t = null;
        
        switch(x){
            
            case XML : t = new XMLTransformer(); break;
            
            case NETWORK : t = new NetworkTransformer(); break; 
            
            default: throw new IOException("Bad request.");
        }
        return t;
    }
      
    
    public static void main (String[] ...args) throws IOException{
        
        TransformerFactory.getTransformer(TransformerType.XML);
         
        TransformerFactory.getTransformer(TransformerType.NETWORK);
           
    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 17, 2019 7:01 pm
by admin
The transform method should take a String argument. This is the input that it has to transform!

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 17, 2019 7:16 pm
by OCAJO1
Just so I'm clear - Are you saying to get rid of the enum all together or change the enum to String to pass to transform method? Even so, how does that gets calling transform method out of the constructors?

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed Apr 17, 2019 9:36 pm
by admin
Please read the problem statement carefully. I am talking about the transform method not the getTransformer method.
Here is the code:

Code: Select all


abstract class Transformer{
  public String transform(String data) throws Exception;
}

class XMLTransformer extends Transformer{
public String transform(String data) {
   return "data".toUpperCase(); //or whatever transformation is required
}

class TransformerFactory{
  Transformer getTransformer(String or enum parameter){
     return new XMLTransformer or some other transformer depending on parameter 
  }
}

class TestClass{
   pvsm{
      Transformer t =  TransformerFactory.getTransformer("xml" or enum);
      t.transform("the data you want to transform");
   }
}
That's pretty much it.

Could you please leave a review of the book on Amazon? Here is the link:

https://www.amazon.com/s?k=enthuware&ta ... nb_sb_noss

We would really appreciate it. thank you.

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Thu Apr 18, 2019 1:34 pm
by OCAJO1
Could you please leave a review of the book on Amazon? Here is the link:

https://www.amazon.com/s?k=enthuware&ta ... nb_sb_noss
Of course, I am planning to that after I finished with chapter 12 anyway.

I believe that I have a code that incorporates your code hints and what I've picked up about enum to satisfy exercise 7. What do you think?

Code: Select all

enum TransformerType {
        
    XML, NETWORK
}

abstract class Transformer {
    
    abstract void transform (String Data) throws IOException;
}

class XMLTransformer extends Transformer {
        
    @Override
    public void transform(String Data){
        System.out.println(Data);
    }
}

class NetworkTransformer extends Transformer {
      
    @Override
    public void transform (String Data) throws IOException {
        System.out.println(Data);
    }
}

class TransformerFactory {
    
    public static Transformer getTransformer(TransformerType x) throws IOException{
        

        switch (x) {
            case XML:
                return new XMLTransformer();
            case NETWORK:
                return new NetworkTransformer();
            default:
                throw new IOException("Bad request.");
        }
    }
}

class TestClass {

    public static void main(String[] args) throws IOException {

        Transformer tr;
        
        tr = TransformerFactory.getTransformer(TransformerType.XML);
        tr.transform("xmldata."); 
         
        tr = TransformerFactory.getTransformer(TransformerType.NETWORK);
        tr.transform("data from network.");
        
        /*or for those who are concerned with saving stackflow memory
        
        TransformerFactory.getTransformer(TransformerType.XML).transform("xmldata.");
        TransformerFactory.getTransformer(TransformerType.NETWORK).transform("data from network.");
        
        */

    }
}

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Thu Apr 18, 2019 7:40 pm
by admin
Yes, this is good :thumbup:

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed May 29, 2019 4:45 am
by zeldalex
For question 5, the following code won't be able to print calories based on actual type of pie, it will only refer to the static method at the superClass and always print 100.

Code: Select all

class Pie{
    public void makePie(){
        System.out.println("making pie");
    }

    public static int getCalories(){
        return 100;
    }
}

class PumpkinPie extends Pie{
    public void makePie(){
        System.out.println("making PumpkinPie");
    }

    public static int getCalories(){
    return 200;
    }
}

class ApplePie extends Pie{
    public void makePie(){
        System.out.println("making ApplePie");
    }

    public static int getCalories(){
    return 300;
    }
}

class Nutritionist{
    void printCalories(Pie p){
        System.out.println(p.getCalories());
    }
}
It will works fine with the instanceof + casting

Code: Select all

class Nutritionist{
    void printCalories(Pie p){
        if (p instanceof ApplePie)
        System.out.println(((ApplePie)p).getCalories());
        if (p instanceof PumpkinPie)
        System.out.println(((PumpkinPie)p).getCalories());
    }
}

But as I learnt from the book, the getCalories() in subClass shall hide the one in superClass, in this case the hiding(or shadow?) seems not working, and I don't think the combine of instanceof and casting is a good solution, may I know what's the problem with my code?

Re: HD Pg 324, Sec. 11.6.0 - exercises

Posted: Wed May 29, 2019 5:21 am
by admin
There is nothing wrong with the code. p.getCalories(); (as shown in your first Nitritionist class), will indeed invoke Pie's static method.

Your task is to solve the issue. You can try various approaches. Your second Nutrition class is one solution. There is no restriction.