4

I'm fairly confident that there's no way this could work, but I wanted to ask anyway just in case I'm wrong:

I've heard many times that whenever you have a certain number of lines of very similar code in one batch, you should always loop through them.

So say I have something like the following.

setPos1(getCard1());
setPos2(getCard2());
setPos3(getCard3());
setPos4(getCard4());
setPos5(getCard5());
setPos6(getCard6());
setPos7(getCard7());
setPos8(getCard8());
setPos9(getCard9());
setPos10(getCard10());
setPos11(getCard11());
setPos12(getCard12());

There is no way to cut down on lines of code as, e.g., below, right?

for (i = 0; i < 12; i++) {
setPos + i(getCard + i)());
}

I'm sure this will have been asked before somewhere, but neither Google nor SO Search turned up with a negative proof.

Thanks for quickly confirming this!

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
s.d
  • 4,017
  • 5
  • 35
  • 65
  • http://stackoverflow.com/questions/6629995/test-if-a-class-contains-an-instance-variable-based-on-its-name – mKorbel Oct 13 '11 at 15:42

6 Answers6

9

No way to do that specifically in Java without reflection, and I don't think it would be worth it. This looks more like a cue that you should refactor your getcard function to take an integer argument. Then you could loop.

Joe
  • 46,419
  • 33
  • 155
  • 245
  • 2
    Most definitely right about refactoring the functions to take integer arguments. There is no way on earth that having two sets of twelve practically-identical functions makes sense. – Prodicus Oct 13 '11 at 15:44
  • I agree that this seems like bad design. Most probably `pos` and `card` are collections or arrays and thus a getter and setter with an additional index would be way better. – Thomas Oct 13 '11 at 15:45
  • 2
    Ah, never thought about that. Thanks for the hint. Having had a first look at reflection, I agree that this would be shooting cannons at sparrows (as they say in Germany). – s.d Oct 18 '11 at 11:11
  • @baphomet13 - I assume you have seen this: http://www.youtube.com/watch?v=63Y5XjlO4vk – Joe Oct 18 '11 at 11:22
4

This is a simple snippet that shows how to loop through the getters of a certain object to check if the returned values are null, using reflection:

for (Method m : myObj.getClass().getMethods()) {
    // The getter should start with "get" 
    // I ignore getClass() method because it never returns null
    if (m.getName().startsWith("get") && !m.getName().equals("getClass")) {
            // These getters have no arguments
            if (m.invoke(myObj) == null) {
                // Do something
            }
    }
}

Like the others stated, probably it's not an elegant implementation. It's just for the sake of completeness.

gRizzlyGR
  • 306
  • 2
  • 9
3

You could do it via reflection, but it would be cumbersome. A better approach might be to make generic setPos() and getCard() methods into which you could pass the index of the current item.

mcfinnigan
  • 11,442
  • 35
  • 28
  • +1: The fact that you want to set values like this is an indication that having a set/get for each specific value is not a good design for your needs. – unholysampler Oct 13 '11 at 15:44
2

You need to ditch the getter/setter pairs, and use a List to store your objects rather then trying to stuff everything into one God object.

Here's a contrived example:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Foo {
    public static class Card {
        int val;

        public Card(int val) {
            this.val = val;
        }

        public int getVal() {
            return val;
        }

    }

    public static class Position {
        int value;

        public Position(Card card) {
            this.value = card.getVal();
        }
    }

    public static void main(String[] args) {
        List<Card> cards = new ArrayList<Card>(Arrays.asList(new Card(1), new Card(2), new Card(3)));
        List<Position> positions = new ArrayList<Position>();
        for (Card card : cards) {
            positions.add(new Position(card));
        }
    }

}

Sahil Muthoo
  • 12,033
  • 2
  • 29
  • 38
1

You can't dynamically construct a method name and then invoke it (without reflection). Even with reflection it would be a bit brittle.

One option is to lump all those operations into one method like setAllPositions and just call that method.

Alternatively, you could have an array of positions, and then just loop over the array, setting the value at each index.

Card[] cardsAtPosition = new Card[12];

and then something like

public void setCardsAtEachPosition(Card[] valuesToSet) {
   // check to make sure valuesToSet has the required number of cards
   for (i = 0; i < cardsAtPosition.length; i++) {
       cardsAtPosition[i] = valuesToSet[i];
   }
}
hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
0

Reflection would be your only option for your example case.

smp7d
  • 4,947
  • 2
  • 26
  • 48