abstract sclass StringMatcher { // change matches only if returning true abstract bool match(S pat, S input, SS matches); // seems to be the same in all subclasses S apply(S input, SS matches) { ret replaceVars(input, matches); } bool matchAnyPattern(Collection patterns, S input, SS matches) { for (S pat : unnull(patterns)) if (match(pat, input, matches)) true; false; } }