Generic Types

параметризирани типове

Какво знаем за class

  • Създава нов тип

  • Шаблон за обекти

  • Има атрибути и методи

  • Има конструктор

Какво знаем за обектите

  • Създават се с new

  • Съдържат референция

  • Имат състояние

  • Имат тип

Какво знаем за масивите

  • Съдържат еднотипни данни

  • Не можем да променяме размера им

Какво е вектор?

  • Структура от данни

  • Имплементира се с масив

  • Може да се разширява динамично

Какво е структура от данни?

Клас, който дава определен интерфейс за работа с определени данни.

Разлики между примитивен и референтен тип

  • пишат се с малка буква

  • съдържат стойност

  • пишат се с главна буква

  • съдържат референция

Примитивните типове:

Референтните типове:

Проблеми с масивите:

  • Не могат да се разширяват - имат фиксиран размер.

  • Съдържат само един тип данни, който се определя когато се създава масива.

Проблеми с векторите до тук:

  • Съдържат само един тип данни, който се определя когато се пишат.

  • Как може да имаме вектор от int? А от Person?

Това е досадно. Какво е решението?

Съществуват решения, едното от тях е много грозно

Внимание! Не правете това НИКЪДЕ!

Object n;
n = 5;
System.out.println(n);
n = "Kamen";
System.out.println(n);
n = 'a';
System.out.println(n);
 
 5
 Kamen
 a

Защо да не правим това?

Object a;
Object b;
a = 5;
b = 6;
System.out.println(a + b); 
// Exception:
// The operator + is undefined for 
// the argument type(s) java.lang.Object
  • Не можем да ползваме оператори

  • Компилатора не ни помага.

  • Ще гръмне runtime. Когато програмата работи.

Ако искаме да работи можем да cast-нем a и b към int

Object a;
Object b;
a = 5;
b = 6;
System.out.println((int)a + (int)b); 

Е добре де, Камене, ама това не е голям проблем

Object a;
Object b;
a = 5;
b = 6;
System.out.println((char)a + (char)b);
// Exception: 
// java.lang.Integer cannot be cast
// to java.lang.Character

#даамане

Трябва много да внимаваме към какво и кога cast-ваме и какви са стойностите в момента

Cast-ването си има специални правила, идващи от полиморфизма.

За него по-късно.

Object е универсален тип в Java. Всичко е Object.

Object a = "Hello";
Object b = "Java";

System.out.println(a);
System.out.println(b);

Обаче не всичко работи с Object.

Object a = "Hello";
Object b = "Java";

System.out.println(a + b); // ?

Отново, трябва да cast-нем.

Object a = "Hello";
Object b = "Java";

System.out.println((String) a + b); // ?

Нашият вектор е контейнер за данни.

  • Може да добавяме данни.
  • Може да достъпваме данни по индекс.
  • Може да премахваме данни.
  • Може да питаме колко данни има във вектора.

Не се интересуваме от конкретния тип, който пазим във Вектора.

Нашият вектор (int)

public class IntegerVector{
  private int[] data;
  private int capacity = 10;
  private int size = 0;
  public Vector(){ data = new int[capacity];}
  public int size(){ return size; }
  public int get(int i){ return data[i]; }
  public void set(int i, int el){ data[i] = el; }
  public void add(int el) { ... }
  public void remove(int i){ ... }
  public void insert(int i, int el){ ... }
  private void resize(){ ... }
}

Новият вектор (Object)

public class ObjectVector{
  private Object[] data;
  private int capacity = 10;
  private int size = 0;
  public Vector(){ data = new Object[capacity];}
  public int size(){ return size; }
  public Object get(int i){ return data[i]; }
  public void set(int i, Object el){ data[i] = el; }
  public void add(Object el) { ... }
  public void remove(int i){ ... }
  public void insert(int i, Object el){ ... }
  private void resize(){ ... }
}

Как можем да го ползваме:

ObjectVector ov = new ObjectVector();
ov.add(5);
ov.add("Kamen");
ov.add('a');
System.out.println(ov);
  5 Kamen a

Проблем

public static int sum(ObjectVector ov){
  int sum = 0;
  for(int i=0;i<ov.size();i++){
    sum += (int)ov.get(i);
  }
  return sum;
}
  Exception:
  java.lang.String cannot be cast to
  java.lang.Integer

Проблем

Не знаем от какъв тип са данните вътре. А в Java можем да работим с тях само ако им знаем типа.

По-удобно е да направим вектора така, че да съдържа един тип данни, но този тип да се задава при създаването му.

Това се нарича Generic Type

С него можем да създаваме вектори по следния начин:

Vector<Integer> numbers = new Vector<Integer>();
Vector<String> names = new Vector<String>();
Vector<Person> group = new Vector<Person>();

Преди да го направим с Vector едно малко демо с Box

public class Box{
  private int data;
  public Box(int data){
    set(data);
  }
  public int get(){ return data; }
  public void set(int data){ this.data = data; }
}

Преди да го направим с Vector едно малко демо с Box

public class Box<T>{
  private T data;
  public Box(T data){
    set(data);
  }
  public T get(){ return data; }
  public void set(T data){ this.data = data; }
}

Преди да го направим с Vector едно малко демо с Box

Box<Integer> b = new Box<Integer>(5);
System.out.println(b.get());

Box<Person> p;
p = new Box<Person>(new Person("Kamen"));
System.out.println(p.get());
  5
  Kamen

Как да променим нашия вектор?

Съществуват 2 начина за реализация на клас със Generic Type

  1. Масива вътре е от тип T

  2. Масива вътре е от тип Object и се cast-ва преди да се върне на повиквача

Вариант 1

public class Vector<T>{
  private T[] data;
  private int capacity = 10;
  private int size = 0;

  public Vector() {
    data = (T[]) new Object[capacity];
  }
  // ...
  public T get(int index){
    return data[index];
  }
}

Вариант 2

public class Vector<T>{
  private Object[] data;
  private int capacity = 10;
  private int size = 0;

  public Vector() {
    data = new Object[capacity];
  }
  // ...
  public T get(int index){
    return (T)data[index];
  }
}

Generic Types

By Hack Bulgaria

Generic Types

  • 1,908