ååé«é颿°ã®è©±ãšäžç·ã«ãJavaçã§ã¯äžéïŒäžéã¯ã€ã«ãã«ãŒããç»å ŽããŸãããããããªããªãèŠããããªãã®ã§ãã¡ãã£ãšããžã¡ã«å匷ããŠã¿ãããšæããŸãã
ãŸãã¯ãä»åã®ã¹ã±ãŒããŽãŒãã
class Super { private String value; public Super(String value) { this.value = value; } public String getValue() { return value; } @Override public String toString() { return String.format("This is [%s] class, value is [%s]",this.getClass().getName(), value); } } class Basic extends Super { public Basic(String value) { super(value); } } class Sub extends Basic { public Sub(String value) { super(value); } }
Super â Basic â Subã®é ã§ç¶æ¿é¢ä¿ãæãç«ã£ãŠããŸããããã«å¯ŸããŠã以äžã®ãããªã³ãŒããæžããŠã¿ãŸãã
Super s = new Super("super"); Basic b = new Basic("basic"); Sub sub = new Sub("sub"); s = b; b = sub; sub = b; // ã³ã³ãã€ã«ãšã©ãŒ
ããã¯ç¹ã«éåæãããŸããããïŒBasicã¯Superã®ãµãã¯ã©ã¹ãªã®ã§ãSuperåã®å€æ°ã«ä»£å ¥ã§ããŸããBasicãšSubã«ãåãé¢ä¿ãæãç«ã¡ãŸãããŸããSuperã¯Basicã®ãµãã¯ã©ã¹ã§ã¯ãªãã®ã§ãäžäœã¯ã©ã¹ããäžäœã¯ã©ã¹ãžã®ä»£å ¥ã¯ã§ããŸããããªããŠããšã¯ãªããç¶æ¿é¢ä¿ã®ããã¯ã©ã¹ã«å¯Ÿãããããæ®éã®æ±ãæ¹ã ãšæããŸãã
ããã§ã¯ãä»åºŠã¯ãããã®ã€ã³ã¹ã¿ã³ã¹ãæ ŒçŽããListãèããŠã¿ãŸãããã
List<Super> superList = new ArrayList<Super>(); List<Basic> basicList = new ArrayList<Basic>(); List<Sub> subList = new ArrayList<Sub>();
ãããããSuperãBasicãSubãåãã©ã¡ãŒã¿ã«é©çšããListãäœæããŸããããããå ã»ã©ã®å倿°ã®ããã«ãä»£å ¥ã³ãŒããæžããŠã¿ãŸãããã
superList = basicList; // ã³ã³ãã€ã«ãšã©ãŒ basicList = subList; // ã³ã³ãã€ã«ãšã©ãŒ subList = basicList; // ã³ã³ãã€ã«ãšã©ãŒ
ãªããšãå šéšã³ã³ãã€ã«ãšã©ãŒã§ãã
ããŸãããããç¶æ ã«ééããŸãããïŒæ®éã«ããã°ã©ãã³ã°ããŠããåã«ã¯ãããããç¶æ³ã«ééããããšã¯ãªããããããŸããããŸãã以äžã®ãããªã³ãŒãã¯æžããã®ã§ãã»ã©å°ãããšã¯ãªãã®ãããããŸããã
basicList.add(s); // ã³ã³ãã€ã«ãšã©ãŒ
basicList.add(b);
basicList.add(sub);
Basicåã§å®£èšããListã«ãSuperåã®å€æ°ãå ¥ããããªãã®ã¯ããããŸããïŒ
ãšãããããã©ã¡ãŒã¿åãããåãåãåãã¡ãœãããå®çŸ©ããããããšãã¡ãã£ãšç¶æ³ãå€ãã£ãŠããŸãã以äžã®ãããªã¡ãœããã宣èšããŠã¿ãŸãã
public void printList(List<Super> list) { for (Super s : list) { System.out.println(s); } }
äžèšã¡ãœããã«å ã»ã©åListãåŒæ°ã«ããŠåŒã³åºãããšãããšã以äžã®ããã«ãªããŸãã
printList(superList); printList(basicList); // ã³ã³ãã€ã«ãšã©ãŒ printList(subList); // ã³ã³ãã€ã«ãšã©ãŒ
ã¡ãœããã倿°ã宣èšããæã¯ãå¿ èŠãªå ·äœæ§ã倱ããªãç¯å²ã§æãæœè±¡åºŠã®é«ãåã§å®£èšãããšæããããŠãããšæããŸãã®ã§ïŒäŸãã°ãList list = new ArrayList();ã®ããã«æžãïŒããã®ããšãç¥ããã«å ã®printListã¡ãœããã®ãããªå®£èšãããŠããŸããšããã®ãµãã¯ã©ã¹ãæ ŒçŽãããã宣èšãããListãåãåããªãããšã«ãªã£ãŠããŸããŸãã
ããã£ãŠãæå€ãšå°ã£ããããããããªãã§ããããïŒããã§ãSuperåã®ãµãã¯ã©ã¹ãæã£ãListãå«ããŠåãåããããã«ããã«ã¯ã以äžã®ãããªã¡ãœããã«ããå¿ èŠããããŸãã
public static void printListWild(List<? extends Super> list) { for (Super s : list) { System.out.println(s); } }
ããã§ç»å ŽããŠããã? extends Superããäžéã¯ã€ã«ãã«ãŒãã§ããæå³ãšããŠã¯ãå°ãªããšãSuperåã®ãµãã¯ã©ã¹ã§ããããšã匷å¶ããããšããããšã«ãªããŸããæäžäœã決ãŸãã®ã§ãäžéã¯ã€ã«ãã«ãŒãã£ãŠããšã§ããã
å ã®å šãŠã³ã³ãã€ã«ãšã©ãŒã«ãªã£ãŠããŸã£ãListã®å倿°ã®ä»£å ¥é¢ä¿ãããã©ã¡ãŒã¿ã«é©çšããåã®é¢ä¿ãšåãããã«ããã«ã¯ã以äžã®ãããªã³ãŒãã«ããå¿ èŠããããŸãã
List<? extends Super> convariantSuperList = new ArrayList<Super>(); List<? extends Basic> convariantBasicList = new ArrayList<Basic>(); List<? extends Sub> convariantSubList = new ArrayList<Sub>(); convariantSuperList = convariantBasicList; convariantBasicList = convariantSubList; convariantSubList = convariantBasicList; // ã³ã³ãã€ã«ãšã©ãŒ
ãã®ããããã©ã¡ãŒã¿åãããåAã«å¯ŸããŠãç¶æ¿é¢ä¿ã®ããåX â Yãé©çšããå Žåã«A[X] = A[Y]ãæãç«ã€ïŒA[Y]ã¯A[X]ã®ãµãåã§ããïŒããšããå ±å€ïŒConvariantïŒãšèšããŸãã
ã»ãã»ãããªãã°å ±å€ã䜿ãã°ãããã ãïŒãšãªãããã§ãããäºæ ã¯ããç°¡åã§ã¯ãããŸãããå°ã£ãããšã«å ±å€ã䜿ã£ãå Žåã¯ã以äžã®ãããªã³ãŒããéããªããªããŸãã
convariantBasicList.add(s); // ã³ã³ãã€ã«ãšã©ãŒ convariantBasicList.add(b); // ã³ã³ãã€ã«ãšã©ãŒ convariantBasicList.add(sub); // ã³ã³ãã€ã«ãšã©ãŒ
ãªããšããã©ã¡ãŒã¿ã«Basicåãé©çšããListã«BasicåãSubåã®å€æ°ããç»é²ã§ããŸãããSuperåã®å€æ°ãç»é²ã§ããªãã®ã¯ãããšããŠãBasicåãSubåãŸã§ç»é²ã§ããªãã®ã¯ãªãïŒãšããçåãåºãããšæããŸãããããã¯ä»¥äžã®ãããªã³ãŒããèãããšè§£æ±ºããŸãã
List<Sub> subList = new ArrayList<Sub>(); List<? extends Basic> basicList = subList; basicList.add(new Basic("basic")); // ããïŒå ã subListã¯Subã§ãã©ã¡ãŒã¿åããŠããããããâŠïŒïŒå®éã¯ã³ã³ãã€ã«ãšã©ãŒïŒ
ã? extends Basicããšå®£èšãããããšãã£ãŠããã®äžã«å ¥ã£ãŠããã®ã¯Basicã§ãã©ã¡ãŒã¿åããListãšã¯éããŸãããSubåã®ããã«ãµãã¯ã©ã¹ã§ãã©ã¡ãŒã¿åãããŠãããããããŸããããã£ãŠãäžèšã³ãŒããããã³ã³ãã€ã«ãšã©ãŒã«ãªããªãã£ãå ŽåãSubåã§å®£èšããListã«å¯ŸããŠããã®äžäœã¯ã©ã¹ã§ããBasicåã®ã€ã³ã¹ã¿ã³ã¹ãç»é²ã§ããããšã«ãªã£ãŠããŸããå ã ã®å€æ°ã®åãšççŸãçããŠããŸããŸãã
ãããããã¯ã€ã«ãã«ãŒãã䜿ã£ãæžã蟌ã¿ã¯ã§ããªãã®ïŒã£ãŠè©±ã«ãªããŸããããã§ããŸãïŒãã®å Žåã¯ã以äžã®ãããªã³ãŒããèšè¿°ããŸãã
List<? super Super> contravariantSuperList = new ArrayList<Super>(); List<? super Basic> contravariantBasicList = new ArrayList<Basic>(); List<? super Sub> contravariantSubList = new ArrayList<Sub>(); contravariantSuperList = contravariantBasicList; // ã³ã³ãã€ã«ãšã©ãŒ contravariantBasicList = contravariantSubList; // ã³ã³ãã€ã«ãšã©ãŒ contravariantSubList = contravariantBasicList;
ãªããšãå ±å€ã®æãšã¯å€æ°ã®ä»£å ¥é¢ä¿ãéã«ãªããŸãããã®ã? super Basicãã®ãããªèšè¿°ããäžéã¯ã€ã«ãã«ãŒããšåŒã³ãå°ãªããšãBasicã®ã¹ãŒããŒã¯ã©ã¹ã§ããããšããšããæå³ã«ãªããŸããæãäžã®éå±€ãæ±ºãŸãããã§ããããã®å Žåã¯ããããã©ã¡ãŒã¿åãããåAã«å¯ŸããŠãç¶æ¿é¢ä¿ã®ããåX â Yãé©çšããå Žåã«A[Y] = A[X]ãæãç«ã€ïŒA[X]ã¯A[Y]ã®ãµãåã§ããïŒããã«ãªãããããåå€ïŒContravariantïŒãšèšããŸãã
ãªããå ±å€ã§ãåå€ã§ããªãïŒA[X]ãšA[Y]ã®éã«ç¶æ¿é¢ä¿ããªãïŒå Žåã®ããšããéå€ïŒInvariantïŒãšèšãããããããã©ã«ãã«ãªã£ãŠããŸãã
ãã§ãåå€ãšããå Žåã«ã¯å ±å€ã®æã«ã¯ã§ããªãã£ãã以äžã®ãããªã³ãŒããæžããããã«ãªããŸãã
contravariantBasicList.add(s); // ã³ã³ãã€ã«ãšã©ãŒ
contravariantBasicList.add(b);
contravariantBasicList.add(sub);
Basicã§åå€ã«ããListã«å¯ŸããŠãæžã蟌ã¿ãã§ããã®ã¯BasicåãšSubåã§ãããSuperåã¯æžã蟌ãããšãã§ããŸããã
ãã®èŸºããããæå³ãããããªããªã£ãŠããããããªãããšæããŸãã
ãšããããããªãåå€ã ãšæžã蟌ã¿ãã§ããã®ãã«ã€ããŠèããŠã¿ãŸããããã? extends Basicããšæžããå Žåã¯ãå°ãªããšãBasicã®ãµãã¯ã©ã¹ã§ããã°åãåããããã«ãªãã®ã§ãããããã«å¯ŸããŠä»¥äžã®ãããªã³ãŒããèããŠã¿ãŸãããã
List<Super> superList = new ArrayList<Super>(); List<? super Basic> basicList = superList; basicList.add(new Basic("basic")); // å ã Superã®Listã ã£ãã®ã§ãããã¯OKïŒ
æåã®æ¹ã§ããããªã³ãŒããèŠããŸãããïŒ
basicList.add(s); // ã³ã³ãã€ã«ãšã©ãŒ
basicList.add(b);
basicList.add(sub);
Basicåã§å®£èšãããListã¯ãBasicåããã®ãµãã¯ã©ã¹ã®å€æ°ãåãåãããšãã§ããŸãããã ã£ãããå ã®äŸã§ããã°Superåã§å®£èšãããListã«BasicåãSubåã®å€æ°ãæžã蟌ãããšãã§ããŠãäžæè°ã¯ãªãã§ããïŒ
ã€ãŸããäžéãæ±ºãŸãã°æžã蟌ã¿ãã§ããããã«ãªãããšããããšã§ãã
ããããŸãšãããšãèªã¿åºãã«ã¯äžéã¯ã€ã«ãã«ãŒãããæžã蟌ã¿ã«ã¯äžéã¯ã€ã«ãã«ãŒããå©çšãããšããæ³åãæãç«ã¡ãŸããããããååã¡ãã£ãšåºãŠãããgetãšputã®ååãã§ãã
äŸãã°ãããListã®å 容ãå¥ã®Listã«è¿œå ãããããªã¡ãœããã¯ã以äžã®ãããªå®£èšãããå¿ èŠããããŸãã
public <T> void appendList(List<? extends T> fromList, List<? super T> toList) { for (T t : fromList) { toList.add(t); } }
fromListã®å 容ãtoListã«è¿œå ããã³ãŒãã§ããã
ãŸããããã¯å€æåŠçãè«ãè² ã£ãã³ãŒãã«ãå©çšããŸãã
public interface Function1<IN, OUT> { public OUT apply(IN in); } import java.util.*; public class FunctionalCollections { public static <T, S> List<S> map(List<T> list, Function1<? super T, ? extends S> func) { List<S> newList = new ArrayList<S>(); for (T t : list) { newList.add(func.apply(t)); } return newList; } }
åå玹ä»ãã颿°ã€ã³ã¿ãŒãã§ãŒã¹ãšmapã¡ãœããã§ãããFunctionã¯ããåAãåãåã£ãŠå¥ã®åBïŒAã§ããããã©ïŒã«å€æããŠçµæãè¿ãã¯ã©ã¹ãšèŠãããšãã§ããŸãããã£ãŠãããã«ãgetãšputã®ååããæãç«ã¡ãŸããã€ãŸãã倿åŠçãè¡ãã¯ã©ã¹ïŒã¡ãœããã®åŒæ°ã¯åå€ã«ãæ»ãå€ã¯å ±å€ã«ããããšããããšã§ãã
以äžã«ãããã䜿ã£ã倿ã³ãŒãäŸãã
// SuperToBasicã¯ãSuperåãåŒæ°ã«åããBasicåã«å€æããŠè¿ãFunction1ã®ã€ã³ã¹ã¿ã³ã¹ // ä»ãåãèªã¿æ¹ãããŸã FunctionalCollections.map(superList, new SuperToBasic()); FunctionalCollections.map(basicList, new SuperToBasic()); FunctionalCollections.map(subList, new SuperToBasic()); FunctionalCollections.map(superList, new BasicToSub()); // ã³ã³ãã€ã«ãšã©ãŒ FunctionalCollections.map(basicList, new BasicToSub()); FunctionalCollections.map(subList, new BasicToSub()); FunctionalCollections.map(superList, new SubToBasic()); // ã³ã³ãã€ã«ãšã©ãŒ FunctionalCollections.map(basicList, new SubToBasic()); // ã³ã³ãã€ã«ãšã©ãŒ FunctionalCollections.map(subList, new SubToBasic());
åŒæ°ã®Listã«é©çšããåããäœãåãåŒæ°ã«åã倿颿°ã¯ã³ã³ãã€ã«ãšã©ãŒã«ãªããListã«é©çšããåãããäžäœã®åãåŒæ°ã«åã倿颿°ã¯ã³ã³ãã€ã«ãéãã®ã¯çã«é©ã£ãŠããã®ã§ã¯ãªãã§ããããïŒãªãããã®mapã¡ãœããã®åŒæ°ããã? super TããåããšãListã«é©çšããåãšåãååŒæ°ãåã倿颿°ããã³ã³ãã€ã«ãéããªããªããŸãã
ãããŒãé·ãã§ãããããã«éå¢çã¯ã€ã«ãã«ãŒãïŒList<?>ïŒãšååïŒListïŒãå ãããšããžã§ããªã¯ã¹ã®ã¯ã€ã«ãã«ãŒãã®åºç€ã¯ãšããããOKãããªãã§ããããïŒ
âŠãã£ã±é£ããã§ããããããã§ãžã§ããªã¯ã¹ãOKãšèšããªããšããããŸãå³ããããžã§ããªãã¯ãªã¯ã©ã¹ãšãã¡ãœããã宣èšããæã®ããšããä»åã®å 容ã§ã¯ãŸãã£ããè§ŠããŠãŸããããâª
Javaã§ãã®èŸºãã解説ããŠããæžç±ãªã©ãããŸããªãããšããããããããæ¥åããã°ã©ãã«ã¯ããããããªãé åã«ãªã£ãŠããããããªãããšæããŸããèªåã¯ãScalaã®å匷ã§ãã®æŠå¿µãåŠã³ãããããJavaã®çè§£ã«é²ã¿ãŸãããScalaã®æžç±ã ãšãæ¯èŒçãã®èŸºãã¡ãããšè§£èª¬ãããã®ãå€ããã§ããããâŠãŸããç°¡åã§ã¯ãªãã§ããã