简体   繁体   中英

How to combine two methods with identical calculates but different fields

How do I combine two methods that have identical calculations but operate (read and write) different fields of the class. A VERY simplified aircode example:

class TileCalculator 
{
  int length;
  int width;
  int tileLength;
  int tileWidth
  int cols;
  int rows;

  void calculateColumns() 
  {
    this.cols = this.width/this.tileWidth;
  }

  void calculateRows() 
  {
    this.rows = this.length/this.tileLength;
  }

}

As these two methods do exactly the same calculation(s) but just using different fields for their input and output it would seem sensible to combine them but I don't know how.

UPDATE: I think I may have oversimplified it to the point where answerers are trying to solve the specific case. A more realistic example is:

void calculateCols()
{
  int tileCols = width/tileWidth;
  int remainder = width%tileWidth;
  if (remainder==0) {
    // there is an exact number of whole tiles
    fullTileCols = tileCols;
    firstT = tileWidth;
    usedTileCols = tileCols;
  } else {
    // there is a remainder
    fullTileCols = tileCols - 1;
    firstT = (remainder+tileWidth)/2;
    usedTileCols = tileCols + 1;
  }
}

void calculateRows() 
{
  int tileRows = length/tileLength;
  int remainder = length%tileLength;
  if (remainder==0) {
    // there is an exact number of whole tiles
    fullTileRows = tileRows;
    firstCut = tileLength;
    usedTileRows = tileRows;
  } else {
    // there is a remainder
    fullTileRows = tileRows - 1;
    firstCut = (remainder+tileLength)/2;
    usedTileRows = tileRows + 1;
  }
}

I'm not saying a redesign isn't the answer but as you can see there are multiple fields involved so a simple return value probably isn't going to cut it. This is why I am using fields rather than a simple function and the maintainability of the current setup is of concern to me.

No, I wouldn't combine them, I would change them.

  • I'd get rid of rows and cols fields
  • I'd get rid of the above methods as it makes your object's state dependent on these methods always being called before an object is used -- a risky proposition.
  • Instead I'd create two calculated getter methods. This way the calculations are guaranteed to be done when needed.

eg,

public int getColumns() {
  return width / tileWidth;
} 

public int getRows() {
  return length / tileLength;
}

Edit

I suppose you could create a RowCol class that has full, first, and used fields, and that has but one equation for doing the calculation above, and that you create two instances, one for row and one for column in the containing class, but if the rationale for this is to just combine these small methods, I question the need for this, or the benefit. Yes, you should follow the DNRY rule, but I worry more about this when I have three or more repeats of the same code.

You could make a convenience method. In the case you have shown this is actually more typing, longer program, extra complexity etc for no benefit. But if the calculation was more complicated it could be worth it

    int calculate(int a, int b) 
      {
        return a/b;
      }

    void calculateColumns() 
      {
        this.cols = this.calculate(this.width, this.tileWidth);
      }

after the update

you actually want 3 return values(full, first, used) so alter the "calculate" to either return a special class with 3 int or an array of int

Then feed in a and b as before but with the adjusted logic and return the 3 values and set them in the calling function

There is no easy way to do this in Java prior to Java 8. You can do it, but it involves using private internal interfaces and anonymous classes. It isn't worth it unless you're really talking about a lot of common lines of code.

With Java 8 though, you'll be able to use closures which will greatly simplify this kind of cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM