プãƒã‚°ãƒ©ãƒ 言語 ジェãƒãƒªãƒƒã‚¯
目次
概è¦
è¨è¨ˆæ™‚ã§ãªãã€ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆæ™‚ã«åž‹ã‚’決ã‚られるé…列(クラス)
åž‹ã ã‘é•ã£ã¦å‡¦ç†ã®å†…容ãŒåŒã˜ã‚¯ãƒ©ã‚¹ã‚’è¨è¨ˆã™ã‚‹éš›ã«ç”¨ã„ã‚‹
ジェãƒãƒªã‚¯ã‚¹ã€ã‚¸ã‚§ãƒãƒªãƒƒã‚¯ã‚¹
(generic/generics)
ラッパークラス
ラップ(包む)
ã‚¯ãƒ©ã‚¹ã®æ©Ÿèƒ½ã‚’利用ã™ã‚‹éš›ã«ã€
継承ã™ã‚‹ã®ã§ã¯ãªãã€ã‚¯ãƒ©ã‚¹å†…ã§ãã®ã‚¯ãƒ©ã‚¹ã‚’インスタンス化&メソッドを呼ã³å‡ºã—ã€
外部ã‹ã‚‰ã¯åˆ©ç”¨ã™ã‚‹ã‚¯ãƒ©ã‚¹ãŒè¦‹ãˆãªã„様ã«åŒ…ã¿è¾¼ã‚€æ–¹æ³•
class Other{
  void method(){ ~ }
}
class Mine{
  Other other;
  Mine(){
    this.other = new Other();
  }
  void method(){
    this.other.method();
  }
}
public static void main( ~ ){
  Mine mine = new Mine();
  mine.method();
  ※内部ã§ã¯Other.method()ãŒå‘¼ã°ã‚Œã¦ã„る。
}
ã¾ãŸã¯ã€JAVAã«ãŠã„ã¦ã€åŸºæœ¬åž‹ã‚’Objectã¨ã—ã¦ç”¨ã„る為ã®ã‚¯ãƒ©ã‚¹
ã“ã“ã§ã¯ã‚¸ã‚§ãƒãƒªãƒƒã‚¯ã«æ¸¡ã™å¼•æ•°
void method(Object obj)
  ~
}
method(引数);
※引数ã«ã¯Object型を基底クラスã¨ã™ã‚‹åž‹ã—ã‹ä½¿ãˆãªã„
intç‰ã®åŸºæœ¬åž‹ã¯Ã—
Integer i = new Integer(100);
method(i);
ã¯å¯ã€‚
ãªãŠã€IDEã®æ©Ÿèƒ½ã«ã‚ˆã‚Šçµå±€ç›´æŽ¥æ•°å€¤ã‚’渡ã—ã¦ã‚‚コンパイルå¯ã€‚
byte | → | Byte |
short | → | Short |
int | → | Integer |
long | → | Long |
float | → | Float |
double | → | Double |
char | → | Character |
boolean | → | Boolean |
汎用的ãªåž‹
//Tã¯æ±Žç”¨çš„ãªåž‹(命åã¯è‡ªç”±)
public class MyList<T>
{
  T[] _list = new T[1000];
  
  public T this[int index]
  {
    get { return _list[index]; }
    set { _list[index] = value; }
  }
}
public void Form1_Load(object sender, EventArgs e)
{
  MyList<int> myList = new MyList<int>();
  ※T:intã¨ã—ã¦ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’作æˆ
  
  for (var i = 0; i < 10; i++)
  {
    myList[i] = i;
    ※myList[i]ã«stringåž‹ã®å€¤ã‚’入れるã¨ã‚¨ãƒ©ãƒ¼
  }
}
コンパイル時ã«ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹æ©Ÿèƒ½
åž‹ã ã‘ãŒç•°ãªã‚‹å¤§é‡ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹æ™‚ç‰ã«å½¹ç«‹ã¤ã€‚
ベクターã«ã¤ã„ã¦ã¯ã€Œãƒ—ãƒã‚°ãƒ©ãƒ 言語 é…列・リスト/リスト(コレクション)ã€å‚ç…§
#include <vector>
#include <string>
汎用的ãªåž‹ï¼šTを定義
template <typename T>
class Stack
{
private:
  std::vector<T> stack_;
public:
  void Push(T value);
  T Pop();
  bool IsEmpty();
};
template <typename T>
void Stack<T>::Push(T value)
{
  this->stack_.push_back(value);
}
template <typename T>
T Stack<T>::Pop()
{
  T value = this->stack_.back();
  this->stack_.pop_back();
  return value;
}
template <typename T>
bool Stack<T>::IsEmpty()
{
  if (this->stack_.empty())
  {
    return true;
  }
  else
  {
    return false;
  }
}
int main(array<System::String ^> ^args)
{
  // ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ä½œæˆæ™‚ã«åž‹ã‚’決ã‚られる
  Stack<std::string> *myStack = new Stack<std::string>();
  
  bool myBool = myStack->IsEmpty();
  // myBool:True
  myStack->Push("A");
  myStack->Push("B");
  myStack->Push("C");
  std::string myStr = myStack->Pop();
  // myStr:"C"
  myBool = myStack->IsEmpty();
  // myBool:False
  return 0;
}
Public Class MyList(Of T)
  Dim _list(1000) As T
  
  Default Public Property list(ByVal index As Integer) As T
    Get
      Return _list(index)
    End Get
    Set(value As T)
      _list(index) = value
    End Set
  End Property
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
  
  Dim myList As New MyList(Of Integer)
  ※T:Integerã¨ã—ã¦ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’作æˆ
  
  For i As Integer = 0 To 10 Step 1
    myList(i) = i
    ※myList[i]ã«stringåž‹ã®å€¤ã‚’入れるã¨ã‚¨ãƒ©ãƒ¼
  Next i
  
End Sub
public class MyGeneric<T> {
 T t;
 public MyGeneric(T prmT){
  this.t = prmT;
 }
 public T getT(){
  return this.t;
 }
}
public class StudyMain {
 public static void main(String[] args) {
  MyGeneric<String> m1 = new MyGeneric<String>("java");
  String s = m1.getT();
  MyGeneric<Integer> m2 = new MyGeneric<Integer>(100);
  Integer i = m2.getT();
 }
}
ジェãƒãƒªãƒƒã‚¯ãƒ¡ã‚½ãƒƒãƒ‰
public class MyGeneric {
 public <T> T retT(T prmT){
  T t = prmT;
  return t;
 }
}
public class StudyMain {
 public static void main(String[] args) {
  MyGeneric m1 = new MyGeneric();
  String s = m1.retT("Java");
  MyGeneric m2 = new MyGeneric();
  int i = m2.retT(5);
 }
}
ジェãƒãƒªãƒƒã‚¯ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェース
public interface MyInterface<T> {
 public T myMethod();
 public void myMethod(T t);
}
public class MyGeneric implements MyInterface<String> {
 @Override
 public String myMethod() {
  return "Java";
 }
 @Override
 public void myMethod(String t) {
  ~
 }
}
public class StudyMain {
 public static void main(String[] args) {
  MyGeneric m = new MyGeneric();
  String s = m.myMethod();
  m.myMethod("Java");
 }
}
é™çš„ジェãƒãƒªãƒƒã‚¯ã‚¯ãƒ©ã‚¹ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿
{
 public static T myValue { get; set; }
 static MyClass()
 {
  Console.WriteLine(@"åˆæœŸåŒ–");
 }
}
MyClass<string>.myValue = @"aaa";
MyClass<int>.myValue = 100;
MyClass<string>.myValue = @"bbb";
Console.WriteLine(MyClass<string>.myValue);
Console.WriteLine(MyClass<int>.myValue);
→
åˆæœŸåŒ– ※T=string時
åˆæœŸåŒ– ※T=int時
bbb
100
※最åˆã®ä½¿ç”¨æ™‚ã®ã¿ã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿ãŒå®Ÿè¡Œã•れる。
制約
基本クラス制約
åž‹(T)ï¼åŸºæœ¬ã‚¯ãƒ©ã‚¹(基底クラス)
class Parent
{
 public string pFunc(string str) { return str; }
}
class Child : Parent { }
class Other {}
åž‹(T)ï¼åŸºæœ¬ã‚¯ãƒ©ã‚¹
class Test<T> where T : Parent
{
 T obj;
 public Test(T o) { this.obj = o; }
 T ã¯Parent型。o ã¯Parentã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹
 public void testFunc(string prm)
 {
  string revStr = this.obj.pFunc(str: prm);
  this.objã¯Parentã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãªã®ã§ã€Parentã®ãƒ¡ãƒ³ãƒãƒ¼é–¢æ•°ã‚’呼ã³å‡ºã—å¯èƒ½
  Console.WriteLine(revStr);
 }
}
class Program
{
 static void Main(string[] args)
 {
  Parent p = new Parent();
  Child c = new Child();
  
  Test<Parent> t1 = new Test<Parent>(o: p);
  t1.testFunc(prm: @"aaa");
  
  基本クラス制約ã®åž‹(クラス)ã¯æ´¾ç”Ÿã‚¯ãƒ©ã‚¹ã§ã‚‚OK
  Test<Child> t2 = new Test<Child>(o: c);
  t2.testFunc(prm: @"aaa");
  
  Other o = new Other();
  Test<Other> t3 = new Test<Other>(o: o);
  →コンパイルエラー:Parentを継承ã—ã¦ã„ãªã„クラスを型パラメータã¨ã—ã¦æŒ‡å®šã§ããªã„
  
  Test<string> t3 = new Test<string>(o: @"aaa");
  →コンパイルエラー:Parentを継承ã—ã¦ã„ãªã„クラスを型パラメータã¨ã—ã¦æŒ‡å®šã§ããªã„
 }
}
 public T myMethod() {
  T t = null;
  return t;
 }
 public void myMethod(T t) {
  ~
 }
}
public class StudyMain {
 public static void main(String[] args) {
  MyGeneric<Integer> m1 = new MyGeneric<Integer>();
  int i = m1.myMethod();
  m1.myMethod(100);
  m1.myMethod(5.5); →エラー
  MyGeneric<Double> m2 = new MyGeneric<Double>();
  Double d = m2.myMethod();
  m2.myMethod(5.5);
  m2.myMethod(100); →エラー
  MyGeneric<String> m1 = new MyGeneric<String>(); →エラー
 }
}
ワイルドカード
public class X{
 public String toString(){
  return "X";
 }
}
public class Y extends X{
 public String toString(){
  return "Y";
 }
}
public class Main {
 list ï¼ Xã€ã¾ãŸã¯Xã®åクラス
 public static void method1(List<? extends X> list){
  実行時ã¾ã§åž‹ä¸æ˜Žã®ç‚ºã€åž‹ã‚’指定ã—ãŸaddã¯ã‚³ãƒ³ãƒ‘イルエラー
  list.add(new X()); エラー
  list.add(new Y()); エラー
  System.out.println(list.get(0));
 }
 list ï¼ Yã€ã¾ãŸã¯Yã®è¦ªã‚¯ãƒ©ã‚¹
 public static void method2(List<? super Y> list){
  実行時ã¾ã§åž‹ä¸æ˜Žã®ç‚ºã€åž‹ã‚’指定ã—ãŸaddã¯ã‚³ãƒ³ãƒ‘イルエラー
  list.add(new X()); エラー
  list.add(new Y()); Yã¯OK
  System.out.println(list.get(0));
  System.out.println(list.get(1));
 }
 public static void main(String[] args) {
  List<X> l1 = new ArrayList<>(); l1.add(new X());
  List<Y> l2 = new ArrayList<>(); l2.add(new Y());
  method1(l1); →X
  method1(l2); →Y
  method2(l1); →X Y
  method2(l2); →Y Y
 }
}
インターフェイス制約
åž‹(T)ï¼æŒ‡å®šã®ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェイスを実装ã—ã¦ã„ã‚‹åž‹(クラス)
interface IParent
{
 string pFunc(string str);
}
class Child : IParent{ }
class Other {}
åž‹(T)ï¼ã‚¤ãƒ³ã‚¿ãƒ¼ãƒ•ェイス
class Test<T> where T : IParent
{
 T obj;
 public Test(T o) { this.obj = o; }
 T ã¯IParentを継承ã—ãŸåž‹(クラス)。o ã¯ãã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹
 public void testFunc(string prm)
 {
  string revStr = this.obj.pFunc(str: prm);
  this.objã¯IParentを継承ã—ãŸã‚¯ãƒ©ã‚¹ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ãªã®ã§ã€IParentã®ãƒ¡ãƒ³ãƒãƒ¼é–¢æ•°ã‚’呼ã³å‡ºã—å¯èƒ½
  Console.WriteLine(revStr);
 }
}
class Program
{
 static void Main(string[] args)
 {
  Child c = new Child();
  Test<Child> t1 = new Test<Child>(o: c);
  t1.testFunc(prm: @"aaa");
  
  Other o = new Other();
  Test<Other> t2 = new Test<Other>(o: o);
  →コンパイルエラー:IParentを継承ã—ã¦ã„ãªã„クラスを型パラメータã¨ã—ã¦æŒ‡å®šã§ããªã„
  
  Test<string> t3 = new Test<string>(o: @"aaa");
  →コンパイルエラー:IParentを継承ã—ã¦ã„ãªã„クラスを型パラメータã¨ã—ã¦æŒ‡å®šã§ããªã„
 }
}
コンストラクタ制約
åž‹(T)ï¼ãƒ‡ãƒ•ォルトコンストラクタãŒå®Ÿè£…ã•れã¦ã„ã‚‹åž‹(クラス)
{
 public MyClass1(string prm){}
}
class MyClass2
{
 public MyClass2(){}
 public MyClass2(string prm){}
}
class Test<T> where T : new()
{
 public Test()
 {
  T t = new T();
  コンストラクタ制約ãŒã‚ã‚‹ã®ã§ã‚¸ã‚§ãƒãƒªãƒƒã‚¯åž‹(クラス)ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹ã‚’作æˆã§ãる。
  制約ãŒç„¡ã‘れã°ã‚³ãƒ³ãƒ‘イルエラー
 }
}
static void Main(string[] args)
{
 Test<MyClass1> t1 = new Test<MyClass1>();
 MyClass1ã¯ãƒ‡ãƒ•ォルトコンストラクタãŒå®šç¾©ã•れã¦ã„ãªã„ã®ã§ã‚³ãƒ³ãƒ‘イルエラー
 
 Test<MyClass2> t2 = new Test<MyClass2>();
 MyClass2ã¯ãƒ‡ãƒ•ォルトコンストラクタãŒã‚ã‚‹ã®ã§å¤šé‡å®šç¾©ãŒã‚ã£ã¦ã‚‚OK
}
newInstanceメソッドã§ä»£æ›¿ã™ã‚‹
public <T> T func(Class<T> clazz, String prm) {
 T t = null;
 try {
  t = clazz.newInstance();
  t.~ = prm
 } catch (InstantiationException e) {
  ~
 }
 return t;
}
å‚照型制約
åž‹(T)ï¼å‚ç…§åž‹
{
 T obj;
 public Test(T prm)
 {
  this.obj = prm;
 }
}
static void Main(string[] args)
{
 Test<string> t = new Test<string>(prm: @"aaa");
 Test<string> t = new Test<string>(prm: null);
 Test<string> t = new Test<string>(prm: string.Empty);
 Test<MyClass> t = new Test<MyClass>(prm: new MyClass());
 Test<Test<string>> t = new Test<Test<string>>(prm: new Test<string>(prm: @"aaa"));
 ↓ コンパイルエラー
 Test<int> t = new Test<int>(prm: 5);
 Test<bool> t = new Test<bool>(prm: true);
}
値照型制約
åž‹(T)ï¼å€¤åž‹
{
 T obj;
 public Test(T prm)
 {
  this.obj = prm;
 }
}
struct MyStruct
{
 public int myInt;
}
class MyClass { }
static void Main(string[] args)
{
 Test<int> t = new Test<int>(prm: 5);
 Test<bool> t = new Test<bool>(prm: true);
 Test<MyStruct> t = new Test<MyStruct>(prm: new MyStruct() { myInt = 5 });
 
 ↓ コンパイルエラー
 Test<string> t = new Test<string>(prm: string.Empty);
 Test<MyClass> t = new Test<MyClass>(prm: new MyClass());
}
制約ã®é †ç•ª
(1)å‚照型制約ã€å€¤åž‹åˆ¶ç´„ã€åŸºæœ¬ã‚¯ãƒ©ã‚¹åˆ¶ç´„
ã©ã‚Œã‹ï¼‘ã¤ã ã‘
(2)インターフェイス制約
(3)コンストラクタ制約
interface IMyInterface{}
class MyClass{}
○:class Test<T> where T : MyClass, new() { }
○:class Test<T> where T : class, IMyInterface, new() { }
×:class Test<T> where T : IMyInterface, MyClass, new() { } â€»é †åºé•å
×:class Test<T> where T : new(), MyClass, IMyInterface { } â€»é †åºé•å
×:class Test<T> where T : class, struct { } ※(1)é‡è¤‡é•å
複数ã®åž‹ãƒ‘ラメーターã«åˆ¥ã®åˆ¶ç´„を付ã‘ã‚‹å ´åˆ
class Test<T1, T2>
 where T1 : class
 where T2 : struct
{ }