Опубликован: 18.09.2006 | Уровень: специалист | Доступ: свободно | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 10:

Основные конструкции языков Java и C#

Пользовательские типы

В обоих рассматриваемых языках имеются ссылочные типы и типы значений. Объекты ссылочных типов имеют собственную идентичность, а значения такой идентичности не имеют. Объекты ссылочных типов можно сравнивать на совпадение или несовпадение при помощи операторов == и !=. В C# эти операторы могут быть перегружены, поэтому, чтобы сравнить объекты на идентичность, лучше привести их сначала к типу object.

В обоих языках можно создавать пользовательские ссылочные типы, определяя классы и интерфейсы. Кроме того, можно использовать массивы значений некоторого типа. В C# можно определять пользовательские типы значений, а в Java типами значений являются только примитивные.

Клас с представляет собой ссылочный тип, объекты которого могут иметь сложную структуру и могут быть задействованы в некотором наборе операций. Структура данных объектов класса задается набором полей (fields) этого класса. В каждом объекте каждое поле имеет определенное значение, могущее быть ссылкой на другой или тот же самый объект.

Над объектом класса можно выполнять операции, определенные в этом классе. Термин "операция" будет употребляться для обозначения методов обоих языков, а также операторов, методов доступа к свойствам, индексерам и событиям в C# (см. ниже). Для каждой операции в классе определяются ее сигнатура и реализация.

Полная сигнатура операции — это ее имя, список типов, значения которых она принимает в качестве параметров, а также тип ее результата и список типов исключений, которые могут быть выброшены из нее. Просто сигнатурой будем называть имя и список типов параметров операции — этот набор обычно используется для однозначного определения операции в рамках класса. Все операции одного класса должны различаться своими (неполными) сигнатурами, хотя некоторые из них могут иметь одинаковые имена. Единственное исключение из этого правила касается только C# и будет описано ниже.

Реализация операции представляет собой набор инструкций, выполняемых каждый раз, когда эта операция вызывается. Абстрактный класс может не определять реализации для некоторых своих операций — такие операции называются абстрактными. И абстрактные классы, и их абстрактные операции помечаются модификатором abstract.

Поля и операции могут быть статическими (static), т.е. относиться не к объекту класса, а к классу в целом. Для получения значения такого поля достаточно указать класс, в котором оно определено, а не его объект. Точно так же, для выполнения статической операции не нужно указывать объект, к которому она применяется.

Интерфейсссылочный тип, отличающийся от класса тем, что он не определяет структуры своих объектов (не имеет полей) и не задает реализаций для своих операций. Интерфейс — это абстрактный тип данных, над которыми можно выполнять заданный набор операций. Какие конкретно действия выполнятся для данного объекта, зависит от его точного типа (в обоих случаях это может быть класс, реализующий данный интерфейс, а в C# — еще и структурный тип, тоже реализующий данный интерфейс ).

Из последней фразы может быть понятно, что и в Java, и в C# объект может относиться сразу к нескольким типам. Один из этих типов, самый узкий, — точный тип объекта, а остальные (более широкие) являются классами-предками этого типа или реализуемыми им интерфейсами. Точным типом объекта не может быть интерфейс или абстрактный класс, потому что для них не определены точные действия, выполняемые при вызове (некоторых) их операций.

Классы и интерфейсы (а также отдельные операции) в обоих языках могут быть шаблонными (generic), т.е. иметь типовые параметры (соответствующие конструкции введены в Java 5 и C# 2.0). При создании объекта такого класса нужно указывать конкретные значения его типовых параметров.

Примеры деклараций классов и интерфейсов для обоих языков приведены ниже. В обоих случаях определяется шаблонный интерфейс очереди, которая хранит объекты типа-параметра, и класс, реализующий очередь на основе ссылочной структуры. Показан также пример использования такой очереди:

public interface Queue <T>
{
  void put (T o);
  T    get ();
  int  size();
}	using System;

public interface IQueue <T>
{
  void Put (T o);
  T    Get ();
  int  Size();
}
public class LinkedQueue <T>
  implements Queue <T>
{
  public void put (T o)
  {
    if(last == null)
    {
      first = last = new Node <T> (o);
    }
    else
    {
      last.next = new Node <T> (o);
      last = last.next;
    }
    size++;
  }
  
  public T    get ()
  {
    if(first == null) return null;
    else
    {
      T result = first.o;
      if(last == first) last = null;
      first = first.next;
      size--;
      return result;
    }
  }
  
  public int  size()
  {
    return size;
  }



  private Node <T> last  = null;
  private Node <T> first = null;
  private int      size  = 0;
    
  private static class Node <E>
  {

    E        o    = null;
    Node<E>  next = null;
        
    Node (E o)
    {
      this.o = o;
    }
  }
}	public class LinkedQueue <T>
  : IQueue <T>
{
  public void Put (T o)
  {
    if(last == null)
    {
      first = last = new Node <T> (o);
    }
    else
    {
      last.next = new Node <T> (o);
      last = last.next;
    }
    size++;
  }

  public T    Get ()
  {
    if(first == null) return default(T);
    else
    {
      T result = first.o;
      if(last == first) last = null;
      first = first.next;
      size--;
      return result;
    }
  }

  public int  Size()
  {
    return size;
  }



  private Node <T> last  = null;
  private Node <T> first = null;
  private int      size  = 0;
  
  internal class Node <E>
  {

    internal E        o    = default(E);
    internal Node <E> next = null;
      
    internal Node <E> (E o)
    {
      this.o = o;
    }
  }
}
public class Program
{
  public static void main(String[] args)
  {
    Queue<Integer> q = 
      new LinkedQueue<Integer>();
    
    for(int i = 0; i < 10; i++)
      q.put(i*i);
    
    while(q.size() != 0)
      System.out.println
        ("Next element + 1: " +
           (q.get()+1));
  }
}	public class Program
{
  public static void Main()
  {
    Queue<int> q = 
      new LinkedQueue<int>();
    
    for(int i = 0; i < 10; i++)
      q.Put(i*i);
    
    while(q.Size() != 0)
      Console.WriteLine
        ("Next element + 1: " +
          (q.Get()+1));
  }
}
10.1.

Обе программы выдают на консоль текст

Next element + 1: 1
Next element + 1: 2
Next element + 1: 5
Next element + 1: 10
Next element + 1: 17
Next element + 1: 26
Next element + 1: 37
Next element + 1: 50
Next element + 1: 65
Next element + 1: 82

На основе пользовательского или примитивного типа можно строить массивы элементов данного типа. Тип массива является ссылочным и определяется на основе типа элементов массива. Количество элементов массива в обоих языках — это свойство конкретного объекта- массива, которое задается при его построении и далее остается неизменным. В обоих языках можно строить массивы массивов и пр.

В Java можно строить только одномерные массивы из объектов, которые, однако, сами могут быть массивами.

int[] array = new int[3];
String[] array1 =
  new String[]{"First","Second"};
int[][] arrayOfArrays = new int[][]
  {{1, 2, 3}, {4, 5}, {6}};

В C# есть возможность строить многомерные массивы в дополнение к массивам массивов.

int[] array = new int[3];
string[] array1 =
  new string[]{"First","Second"};
int[][] arrayOfArrays = new int[][]
  {{1, 2, 3}, {4, 5}, {6}};
int[,] twoDimensionalArray = 
  new int[,] {{1, 2}, {3, 4}};

Количество элементов в массиве доступно как значение поля length, имеющегося в каждом типе массивов.

Любой тип массива наследует системному типу System.Array, и любой объект-массив имеет все свойства и методы этого типа.

Общее количество элементов в массиве (во всех размерностях) доступно как значение, возвращаемое свойством Length. Количество измерений в массиве — значение свойства Rank.

Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!

Лариса Парфенова
Лариса Парфенова

1) Можно ли экстерном получить второе высшее образование "Программная инженерия" ?

2) Трудоустраиваете ли Вы выпускников?

3) Можно ли с Вашим дипломом поступить в аспирантуру?