Что такое программная музыка? Примеры и определение программной музыки. Большая энциклопедия нефти и газа

Обобщённое программирование Обобщенное программирование - написание кода, который может быть многократно использован с объектами многих различных типов.

В ранних версиях Java это достигалось при помощи наследования, ArrayList содержал массив ссылок на Object. Всякий раз, когда извлекалось значение, необходимо было выполнять приведение типов.

Обобщённое программирование — парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. В том или ином виде поддерживается разными языками программирования.

Обобщения (generics) представляют собой наиболее существенное изменение в языке программирования Java со времен версии 1.0. Появление обобщений в Java 5.0 стало результатом первых требований к спецификации Java (Java Specification Requests — JSR 14), которые были сформулированы в 1999 г. Обобщения понадобились потому, что они позволяют писать более безопасный код, который легче читается, чем код, перегруженный переменными Object и приведениями типов. Обобщения особенно полезны для классов коллекций, таких как вездесущий ArrayList.

Обобщения похожи — по крайней мере, внешне — на шаблоны в C++. В C++, как и в Java, шаблоны впервые были добавлены для поддержки строго типизированных кол- лекций. Однако с годами были открыты и другие их применения.

Возможности обобщённого программирования впервые появились в 70-х годах в языках CLU и Ada, а затем во многих объектно-ориентированных языках, таких как C++, Java, D и языках для платформы.NET. Общий механизм Средства обобщённого программирования реализуются в виде тех или иных синтаксических средств. У функции или типа данных явно описываются формальные параметры-типы. Это описание является обобщённым и в исходном виде непосредственно использовано быть не может.

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

Естественно, что для успешного использования обобщённых описаний фактические типы-параметры должны удовлетворять определённым условиям. Если обобщённая функция сравнивает значения типа-параметра, любой конкретный тип, использованный в ней, должен поддерживать операции сравнения, если присваивает значения типа-параметра переменным — конкретный тип должен обеспечивать корректное присваивание. Способы реализации Известно два основных способа реализации поддержки обобщённого программирования в компиляторе.

Порождение нового кода для каждой конкретизации. В этом варианте компилятор рассматривает обобщённое описание как текстовый шаблон для создания вариантов конкретизаций. Когда компилятору требуется новая конкретизация обобщённого типа или процедуры, он создаёт новый экземпляр типа или процедуры, чисто механически добавляя туда тип-параметр. То есть, имея обобщённую функцию перестановки элементов, компилятор, встретив её вызов для целого типа, создаст функцию перестановки целых чисел и подставит в код её вызов, а затем, встретив вызов для строкового типа — создаст функцию перестановки строк, никак не связанную с первой. Этот метод обеспечивает максимальное быстродействие. Недостатком его является то, что при активном использовании обобщённых типов и функций с различными типами-параметрами размер откомпилированной программы может очень сильно возрастать, поскольку даже для тех фрагментов описания, которые для разных типов не различаются, компилятор всё равно генерирует отдельный код. Этот недостаток можно затушевать путём частичной генерации общего кода (часть обобщённого описания, которая не зависит от типов-параметров, оформляется специальным образом и по ней компилятор генерирует единый для всех конкретизаций код). . Порождение кода, который во время исполнения выполняет преобразование фактических параметров-типов к одному типу, с которым фактически и работает. В этом случае на этапе компиляции программы компилятор лишь проверяет соответствие типов и включает в код команды преобразования конкретного типа-параметра к общему типу. Код, определяющий функционирование обобщённого типа или функции, имеется в откомпилированной программе в единственном экземпляре, а преобразования и проверки типов выполняются динамически, во время работы программы. В этом варианте порождается, как правило, более компактный код, но программа оказывается в среднем медленнее, чем в первом варианте, из-за необходимости выполнения дополнительных операций и меньших возможностей оптимизации. Кроме того, в компилированный код для типов-параметров далеко не всегда включается динамическая информация о типах (в первом варианте она есть, если вообще поддерживается, поскольку конкретизации для каждого типа-параметра различны), что определяет некоторые ограничения на применение обобщённых типов и функций. Подобные ограничения есть в Java.

Обобщенный класс - это класс с одной или более переменной типа. class Pair {} Переменная типа используется для спецификации типа возрата методов и типов полей и локальных переменных. Затем можно создать обьект обобщенного типа, подставляя имя типа вместо переменной типа. Pair ()

Некоторые ограничения на обобщения 1. Параметры типа не могут принимать примитивные типы. 2. Массивы параметризованных типов не разрешены. 3. Нельзя создавать экземпляры переменных типов. 4. В статическом контексте не разрешены. Назначение обобщенного программирования Обобщенное программирование означает написание кода, который может быть многократно использован с объектами многих различных типов. Это облегчает чтение вашего кода. Вы можете сразу понять, что этот конкретный массив-список содержит объекты String. Компилятор также может успешно использовать эту информацию. Не требуется никакого приведения при вызове get(). Компилятор знает, что типом возврата этого метода является String, а не Object: String filename = files.get(0); Компилятор также знает, что метод add() в ArrayList имеет параметр типа String. Это намного безопаснее, чем иметь дело с параметром типа Object. Теперь компилятор может проконтролировать, чтобы вы не вставили объект неверного типа. Например, следующий оператор не скомпилируется: files.add(new File("...")); // в ArrayList можно добавлять // только объекты String Ошибка компиляции — это намного лучше, чем исключение приведения типа во время выполнения. В этом привлекательность параметров типа: они делают вашу программу легче читаемой и более безопасной. Такие обобщенные классы, как ArrayList, использовать легко. И большинство программистов Java просто применяют типы вроде ArrayList — как если бы они были частью языка, подобно массивам String. (Разумеется, массивы-списки лучше простых массивов, поскольку могут автоматически расширяться.) Однако реализовать обобщенный класс не так просто. Программисты, которые будут использовать ваш код, попытаются подставлять всевозможные классы вместо ваших параметров типа. Они ожидают, что все будет работать без досадных ограничений и запутанных сообщений об ошибках. Ваша задача как обобщенного программиста — предвидеть все возможные будущие применения вашего класса. Обобщенный код и виртуальная машина Виртуальная машина не имеет дела с объектами обобщенных типов — все объекты принадлежат обычным классам. Всякий раз при определении обобщенного типа автоматически создается соответствующий ему “сырой” (raw) тип. Имя этого типа совпадает с именем обобщенного типа с удаленными параметрами типа. Переменные типа удаляются и заменяются ограничивающими типами (или типом Object, если переменная не имеет ограничений). Например, “сырой” тип для Pair выглядит, как показано ниже. public class Pair { public Pair(Object first, Object second) { this.first = first; this.second = second; } public Object getFirst() { return first; } public Object getSecond() { return second; } public void setFirst(Object newValue) { first = newValue; } public void setSecond(Object newValue) { second = newValue; } private Object first; private Object second; } Поскольку T — неограниченная переменная типа, она просто заменяется Object. В результате получается обычный класс вроде тех, что вы могли реализовать раньше, до появления средств обобщений в язык программирования Java. Ваши программы содержат разные варианты Pair, такие как Pair или Pair, но такая “подчистка” превращает их в “сырой” тип Pair. “Сырой” тип заменяет переменные типов первым ограничением или же Object, если никаких ограничений не предусмотрено. Например, переменная типа в классе Pair не имеет явных ограничений, а потому сырой тип заменяет T на Object. Предположим, что объявлен немного отличающийся тип: public class Interval implements Serializable { public Interval(T first, T second) { if (first.compareTo(second) <= 0) { lower = first; upper = second; } else { lower = second; upper = first; } } ... private T lower; private T upper; } Сырой тип Interval выглядит следующим образом: public class Interval implements Serializable { public Interval(Comparable first, Comparable second) { ... } ... private Comparable lower; private Comparable upper; } Трансляция обобщенных выражений Когда ваша программа вызывает обобщенный метод, компилятор вставляет приведения, когда удаляется возвращаемый тип. Например, рассмотрим следующую последовательность операторов: Pair buddies = ...; Employee buddy = buddies.getFirst(); Подчистка getFirst() приведет к возврату типа Object. Компилятор автоматически вставит приведение к Employee. То есть компилятор транслирует вызов метода в две инструкции виртуальной машины. . Вызов сырого метода Pair.getFirst(). . Приведение возвращенного объекта Object к типу Employee. Приведения также вставляются при обращении к обобщенному полю. Предположим, что поля first и second были бы общедоступными, т.е. public. (Возможно, это нехороший стиль программирования, но вполне допустимый в Java.) Тогда в оператор Employee buddy = buddies.first; в результирующем байт-коде также будут вставлены приведения.

Объектно-ориентированный компонент языка С++ обладает весьма мощными возможностями. В языке С++ имеется развитый аппарат классов, позволяющий реализовать пользовательские типы данных. Перегрузка встроенных операторов для пользовательских типов позволяет наделить эти типы всеми возможностями, которые предусмотрены в языке для встроенных типов. Это дает основания считать систему встроенных типов языка С++ расширяемой.

Класс языка С++ является обобщением структур языка С. От структур языка С класс отличается в двух отношениях. Во-первых, в классе объединяются не только данные, но функции. Во-вторых, элементы класса наделяются правами доступа. Объединение данных и функций позволяет связать данные и те операции, которые необходимо с ними выполнять, Права доступа позволяют инкапсулировать (скрыть) реализацию класса.

В языке С++ пользовательские типы могут быть наделены свойствами наследования и полиморфизма. Это позволяет программисту разрабатывать иерархические программные системы.

Важным является то обстоятельство, что имеется стандарт, утвержденный в 1998 поду, который определяет синтаксис языка С++ и его стандартную библиотеку.

Отметим, что в объектно-ориентированном программировании в центре внимания являются данные, а не алгоритмы как это имеет место в процедурном программировании.

Обобщенное программирование

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

template void swap(T &a, T &b) { T temp = a; a = b; b = temp; } int main() { double x = 2; double y = 3; swap(x, y); printf(“x= %0.4g y= %0.4g\n”, x, y); int n = 4; int m = 5; swap(n, m); printf(“n= %d m= %d\n”, n, m); return 0; }

Приведенный выше программный код начинается с определения шаблона функции swap(). Шаблон функции отличается от определения обычной функции наличием дополнительного префикса, который начинается с зарезервированного словаtemplate. В угловых скобках содержится так называемый список параметров шаблона. В рассматриваемом примере этот список содержит только один элемент, состоящий из зарезервированного словаclassимени параметра шаблонаT. Зарезервированное словоclassпоказывает, что параметр шаблонаTотносится к категории обобщенных типов (имеются и другие разновидности шаблонных параметров).

В вызывающей функции, которой

На пути к объектно-ориентированному программированию

Общеизвестно, что сложность программирования в первую очередь обусловлена сложностью решаемых задач. Основным способом преодоления этих трудностей является декомпозиция поставленной задачи. Декомпозиция состоит в замене исходной задачи совокупностью других менее сложных задач, совместное решение которых должно дать ожидаемый результат.

Следует учитывать тот факт, что не любая декомпозиция приводит к успеху. На практике часто приходиться сталкиваться с ситуацией, когда части программы, отвечающие за решение отдельных подзадач, работают, а вся программа в целом нет. Это имеет место при наличии сильных взаимосвязей между отдельными частями программы.

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

В ранних языках программирования нашла применение так называемая абстракция действия, или процедурная абстракция. Абстракция действия реализуется с помощью подпрограмм (функциями языка С).

Существуют два основных вида абстракций:

    Абстракция действия (процедурная абстракция).

    Абстракция сущности (абстрактный тип данных).

Абстракция действия, или процедурная абстракция реализуется в языке C++ с помощью аппарата функций. Используя функции, программист имеет возможность расширять то множество встроенных операций, которые предусмотрены языком.

При использовании процедурного программирования является единственным поддерживаемым способом абстрагирования. Рассмотрим факторы, обеспечивающие поддержку языком Cабстракции действия:

    наличие специальной синтаксической конструкции, предназначенной для реализации абстракции (определение функции).

    возможность отделения интерфейса от реализации.

    сокрытие реализации алгоритма, реализующего действие, от клиента.

Абстракция сущностей тесно связана с проблемой создания пользовательских типов данных. Дело в том, что на практике часто возникает потребность в моделировании понятий, существующих в той предметной области, для которой разрабатывается программа. Это и приводит к необходимости иметь аппарат, позволяющий создавать пользовательские типы данных. Представляет интерес рассмотреть вопрос следующий вопрос: можно или нет на языке типа языка С реализовать абстракцию сущностей. Из изложенного ранее, можно отметить важный факт, который может негативно сказаться на попытке реализовать абстракцию действия: в языке С отсутствует синтаксическая конструкция, предназначенная для этих целей.

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

Последнее обновление: 28.09.2017

C выходом версии 2.0 фреймворк.NET стал поддерживать обобщенные типы (generics), а также создание обобщенных методов. Чтобы разобраться в особенности данного явления, сначала посмотрим на проблему, которая могла возникнуть до появления обобщенных типов. Посмотрим на примере. Допустим, мы определяем класс для представления банковского счета. К примеру, он мог бы выглядеть следующим образом:

Class Account { public int Id { get; set; } public int Sum { get; set; } }

Класс Account определяет два свойства: Id - уникальный идентификатор и Sum - сумму на счете.

Здесь идентификатор задан как числовое значение, то есть банковские счета будут иметь значения 1, 2, 3, 4 и так далее. Однако также нередко для идентификатора используются и строковые значения. И у числовых, и у строковых значений есть свои плюсы и минусы. И на момент написания класса мы можем точно не знать, что лучше выбрать для хранения идентификатора - строки или числа. Либо, возможно, этот класс будет использоваться другими разработчиками, которые могут иметь свое мнение по данной проблеме.

И на первый взгляд, чтобы выйти из подобной ситуации, мы можем определить свойство Id как свойство типа object. Так как тип object является универсальным типом, от которого наследуется все типы, соответственно в свойствах подобного типа мы можем сохранить и строки, и числа:

Class Account { public object Id { get; set; } public int Sum { get; set; } }

Затем этот класс можно было использовать для создания банковских счетов в программе:

Account account1 = new Account { Sum = 5000 }; Account account2 = new Account { Sum = 4000 }; account1.Id = 2; account2.Id = "4356"; int id1 = (int)account1.Id; string id2 = (string)account2.Id; Console.WriteLine(id1); Console.WriteLine(id2);

Все вроде замечательно работает, но такое решение является не очень оптимальным. Дело в том, что в данном случае мы сталкиваемся с такими явлениями как упаковка (boxing) и распаковка (unboxing) .

Так, при присвоении свойству Id значения типа int, происходит упаковка этого значения в тип Object:

Account1.Id = 2; // упаковка в значения int в тип Object

Чтобы обратно получить данные в переменную типов int, необходимо выполнить распаковку:

Int id1 = (int)account1.Id; // Распаковка в тип int

Упаковка (boxing) предполагает преобразование объекта значимого типа (например, типа int) к типу object. При упаковке общеязыковая среда CLR обертывает значение в объект типа System.Object и сохраняет его в управляемой куче (хипе). Распаковка (unboxing), наоборот, предполагает преобразование объекта типа object к значимому типу. Упаковка и распаковка ведут к снижению производительности, так как системе надо осуществить необходимые преобразования.

Кроме того, существует другая проблема - проблема безопасности типов. Так, мы получим ошибку во время выполнения программы, если напишем следующим образом:

Account account2 = new Account { Sum = 4000 }; account2.Id = "4356"; int id2 = (int)account2.Id; // Исключение InvalidCastException

Мы можем не знать, какий именно объект представляет Id, и при попытке получить число в данном случае мы столкнемся с исключением InvalidCastException.

Эти проблемы были призваны устранить обобщенные типы. Обобщенные типы позволяют указать конкретный тип, который будет использоваться. Поэтому определим класс Account как обощенный:

Class Account { public T Id { get; set; } public int Sum { get; set; } }

Угловые скобки в описании class Account указывают, что класс является обобщенным, а тип T, заключенный в угловые скобки, будет использоваться этим классом. Необязательно использовать именно букву T, это может быть и любая другая буква или набор символов. Причем сейчас нам неизвестно, что это будет за тип, это может быть любой тип. Поэтому параметр T в угловых скобках в еще называется универсальным параметром , так как вместо него можно подставить любой тип.

Например, вместо параметра T можно использовать объект int, то есть число, представляющее номер счета. Это также может быть объект string, либо или любой другой класс или структура:

Account account1 = new Account { Sum = 5000 }; Account account2 = new Account { Sum = 4000 }; account1.Id = 2; // упаковка не нужна account2.Id = "4356"; int id1 = account1.Id; // распаковка не нужна string id2 = account2.Id; Console.WriteLine(id1); Console.WriteLine(id2);

Поскольку класс Account является обобщенным, то при определении переменной после названия типа в угловых скобках необходимо указать тот тип, который будет использоваться вместо универсального параметра T. В данном случае объекты Account типизируется типами int и string:

Account account1 = new Account { Sum = 5000 }; Account account2 = new Account { Sum = 4000 };

Поэтому у первого объекта account1 свойство Id будет иметь тип int, а у объекта account2 - тип string.

При попытке присвоить значение свойства Id переменной другого типа мы получим ошибку компиляции:

Account account2 = new Account { Sum = 4000 }; account2.Id = "4356"; int id1 = account2.Id; // ошибка компиляции

Тем самым мы избежим проблем с типобезопасностью. Таким образом, используя обобщенный вариант класса, мы снижаем время на выполнение и количество потенциальных ошибок.

Значения по умолчанию

Иногда возникает необходимость присвоить переменным универсальных параметров некоторое начальное значение, в том числе и null. Но напрямую мы его присвоить не можем:

T id = null;

В этом случае нам надо использовать оператор default(T) . Он присваивает ссылочным типам в качестве значения null, а типам значений - значение 0:

Class Account { T id = default(T); }

Статические поля обобщенных классов

При типизации обобщенного класса определенным типом будет создаваться свой набор статических членов. Например, в классе Account определено следующее статическое поле:

Class Account { public static T session; public T Id { get; set; } public int Sum { get; set; } }

Теперь типизируем класс двумя типами int и string:

Account account1 = new Account { Sum = 5000 }; Account.session = 5436; Account account2 = new Account { Sum = 4000 }; Account.session = "45245"; Console.WriteLine(Account.session); // 5436 Console.WriteLine(Account.session); // 45245

В итоге для Account и для Account будет создана своя переменная session.

Использование нескольких универсальных параметров

Обобщения могут использовать несколько универсальных параметров одновременно, которые могут представлять различные типы:

Class Transaction { public U FromAccount { get; set; } // с какого счета перевод public U ToAccount { get; set; } // на какой счет перевод public V Code { get; set; } // код операции public int Sum { get; set; } // сумма перевода }

Здесь класс Transaction использует два универсальных параметра. Применим данный класс:

Account acc1 = new Account { Id = 1857, Sum = 4500 }; Account acc2 = new Account { Id = 3453, Sum = 5000 }; Transaction, string> transaction1 = new Transaction, string> { FromAccount = acc1, ToAccount = acc2, Code = "45478758", Sum = 900 };

Здесь объект Transaction типизируется типами Account и string. То есть в качестве универсального параметра U используется класс Account, а для параметра V - тип string. При этом, как можно заметить, класс, которым типизируется Transaction, сам является обобщенным.

Обобщенные методы

Кроме обобщенных классов можно также создавать обобщенные методы, которые точно также будут использовать универсальные параметры. Например:

Class Program { private static void Main(string args) { int x = 7; int y = 25; Swap(ref x, ref y); Console.WriteLine($"x={x} y={y}"); // x=25 y=7 string s1 = "hello"; string s2 = "bye"; Swap(ref s1, ref s2); Console.WriteLine($"s1={s1} s2={s2}"); // s1=bye s2=hello Console.Read(); } public static void Swap (ref T x, ref T y) { T temp = x; x = y; y = temp; } }

Здесь определен обощенный метод Swap, который принимает параметры по ссылке и меняет их значения. При этом в данном случае не важно, какой тип представляют эти параметры.

В методе Main вызываем метод Swap, типизируем его определенным типом и передаем ему некоторые значения.

Н. А. Римского-Корсакова «Шехеразада», перед нами возникают образы жестокого султана Шахрияра, искусной сказительницы Шехеразады, величественная картина моря и уплывающий вдаль корабль Синдбада-морехода. Арабские сказки «Тысяча и одна ночь» стали программой этого замечательного произведения. Римский-Корсаков кратко изложил ее в литературном предисловии. Но уже название сюиты направляет внимание слушателей на восприятие определенного содержания.

Г. Берлиоз.

К программным (от греческого «программа» - «объявление», «распоряжение») относятся музыкальные произведения, которые имеют определенный заголовок или литературное предисловие, созданное или избранное самим композитором. Благодаря конкретному содержанию программная музыка более доступна и понятна слушателям. Ее выразительные средства особенно рельефны и ярки. В программных произведениях композиторы широко используют оркестровую звукопись, изобразительность, сильнее подчеркивают контраст между образами-темами, разделами формы и др.

Богат и разнообразен круг образов и тем программной музыки. Это и картина природы - нежные краски «Рассвета на Москве-реке» в увертюре к опере М. П. Мусоргского «Хованщина»; мрачное Дарьяльское ущелье, Терек и замок царицы Тамары в симфонической поэме М. А. Балакирева «Тамара»; поэтичные пейзажи в произведениях К. Дебюсси «Море», «Лунный свет». Сочные, колоритные картины народных праздников воссозданы в симфонических произведениях М. И. Глинки «Камаринская» и «Арагонская хота».

Многие сочинения этого вида музыки связаны с замечательными произведениями мировой литературы. Обращаясь к ним, композиторы в музыке стремятся раскрыть те нравственные проблемы, над которыми размышляли поэты, писатели. К «Божественной комедии» Данте обращались П. И. Чайковский (фантазия «Франческа да Римини»), Ф. Лист («Симфония к „Божественной комедии" Данте»). Трагедией У. Шекспира «Ромео и Джульетта» вдохновлены одноименные симфония Г. Берлиоза и увертюра-фантазия Чайковского, трагедией «Гамлет» - симфония Листа. Одна из лучших увертюр Р. Шумана написана к драматической поэме Дж. Г. Байрона «Манфред». Пафос борьбы и победы, бессмертие подвига героя, отдавшего жизнь за свободу родины, выразил Л. Бетховен в увертюре к драме И. В. Гёте «Эгмонт».

К программным произведениям относятся сочинения, которые принято называть музыкальными портретами. Это фортепьянная прелюдия Дебюсси «Девушка с волосами цвета льна», пьеса для клавесина «Египтянка» Ж. Ф. Рамо, фортепьянные миниатюры Шумана «Паганини» и «Шопен».

Иногда программа музыкального сочинения бывает навеяна произведениями изобразительного искусства. В фортепьянной сюите «Картинки с выставки» Мусоргского отразились впечатления композитора от выставки картин художника В. А. Гартмана.

Масштабные, монументальные произведения программной музыки связаны с важнейшими историческими событиями. Таковы, например, симфонии Д. Д. Шостаковича «1905 год», «1917 год», посвященные 1-й русской революции 1905-1907 гг. и Октябрьской революции.

Программная музыка издавна привлекала многих композиторов. Изящные пьесы в стиле рококо писали для клавесина французские композиторы 2-й половины XVII - начала XVIII в. Л. К. Дакен («Кукушка»), Ф. Куперен («Сборщицы винограда»), Рамо («Принцесса»). Итальянский композитор А. Вивальди четыре скрипичных концерта объединил под общим названием «Времена года». В них созданы тонкие музыкальные зарисовки природы, пасторальные сценки. Содержание каждого концерта композитор изложил в развернутой литературной программе. И. С. Бах одну из пьес для клавира шутливо назвал «Каприччо на отъезд возлюбленного брата». В творческом наследии Й. Гайдна больше 100 симфоний. Среди них есть и программные: «Утро», «Полдень», «Вечер и буря».

Важное место заняла программная музыка в творчестве композиторов-романтиков . Портреты, жанровые сценки, настроения, тончайшие оттенки человеческих чувств тонко и вдохновенно раскрыты в музыке Шумана (фортепьянные циклы «Карнавал», «Детские сцены», «Крейслериана», «Арабеска»). Своеобразным музыкальным дневником стал большой фортепьянный цикл Листа «Годы странствий». Под впечатлением от поездки в Швейцарию написаны им пьесы «Часовня Вильгельма Телля», «Женевские колокола», «На Валлендштадском озере». В Италии композитора покорило искусство великих мастеров эпохи Возрождения . Поэзия Петрарки, картина Рафаэля «Обручение», скульптура Микеланджело «Мыслитель» стали своеобразной программой в музыке Листа.

Французский симфонист Г. Берлиоз воплощает принцип программности не обобщенно, а последовательно раскрывает сюжет в музыке. «Фантастическая симфония» имеет развернутое литературное предисловие, написанное самим композитором. Герой симфонии попадает то на бал, то в поле, то идет на казнь, то оказывается на фантастическом шабаше ведьм. С помощью красочного оркестрового письма Берлиоз добивается почти зрительных картин театрального действия.

К программной музыке часто обращались русские композиторы. Фантастические, сказочные сюжеты легли в основу симфонических картин: «Ночь на Лысой горе» Мусоргского, «Садко» Римского-Корсакова, «Баба-Яга», «Кикимора», «Волшебное озеро» А. К. Лядова. Созидательную силу человеческой воли и разума воспел А. Н. Скрябин в симфонической поэме «Прометей» («Поэма огня»).

Программная музыка занимает большое место в творчестве советских композиторов. Среди симфоний Н. Я. Мясковского есть «Колхозная», «Авиационная». С. С. Прокофьев написал симфоническое произведение «Скифская сюита», фортепьянные пьесы «Мимолетности», «Сарказмы»; Р. К. Щедрин - концерты для оркестра «Озорные частушки», «Звоны»; М. К. Койшибаев - поэму для оркестра казахских народных инструментов «Советский Казахстан»; З. М. Шахиди - симфоническую поэму «Бузрук».

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

Конкретика и синтез

По идее, вся музыка в той или иной степени программна, разве что почти невозможно в точности обозначить ни предметы, ни понятия, которые вызывают те или иные чувства у слушателя. Такими способностями обладает только речь, устная или письменная. Поэтому композиторы нередко снабжают свои произведения программой, таким образом заставляя словесную или литературную предпосылку работать в синтезе со всеми применёнными им музыкальными средствами.

Единству литературы и музыки помогает то, что оба эти вида искусства способны показывать развитие и рост образа во времени. Различные виды творческих действий были объединены ещё с древности, поскольку искусство родилось и развивалось в синкретическом виде, связываясь с ритуалами и трудовой деятельностью. В средствах оно было очень ограниченным, поэтому по отдельности и без прикладных задач просто не могло существовать.

Размежевание

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

Это могут быть названия, которые предусматривает программная музыка. Примеры - в сборнике фортепианных пьес П. И. Чайковского где у каждой пьесы есть не только "говорящее", но и "рассказывающее" название: "Утренняя молитва", "Нянина сказка", "Болезнь куклы" и все остальные маленькие произведения. Это его же сборник для детей постарше "Времена года", где к названию Пётр Ильич присовокупил и яркий поэтический эпиграф. Композитор позаботился о конкретном содержании музыки, тем и объясняя, что такое программная музыка и как нужно исполнять данное произведение.

Музыка плюс литература

Программная музыка для детей особенно понятна, если у произведения есть и название, и сопроводительное слово, которое составляет сам композитор или писатель, вдохновивший его, как сделал Римский-Корсаков в симфонической сюите "Антар" по сказке Сенковского или Свиридов в музыке к повести

Тем не менее программа музыку лишь дополняет, не являясь точным разъяснением. Просто объект вдохновения один и тот же у писателя и композитора, а средства всё-таки разные.

Музыка минус литература

Если пьеса называется "Грустная песенка" (например, есть у Калинникова, Свиридова и многих других композиторов), это определяет только характер исполнения, но никак не конкретное содержание, тем и различны программная и непрограммная музыка. Конкретика - это "Собачка потерялась", "Клоуны", "Дедушкины часы" (которые потикают-потакают, а потом непременно будут бить). Такова практически вся программная музыка для детей, она глубже и быстрее понимается и лучше усваивается.

Музыкальный язык чаще всего сам конкретизирует программное содержание посредством своей изобразительности: звучание может имитировать пение птиц ("Жаровонок", "Кукушка"), нагнетание напряжённости, веселье народного гулянья, ярмарочные шумы ("Необычайное происшествие", "Масленица" и другие. Это так называемая звукопись, которая тоже проясняет, что такое программная музыка.

Определение

Любое снабжённое словесной характеристикой произведение обязательно содержит элементы программности, которая имеет множество видов. А что такое программная музыка, можно понять, даже слушая или разучивая этюды. Они сами по себе призваны развивать технические возможности музыканта в роли развёрнутых упражнений и могут не только программы не содержать, но и музыки как таковой, но всё равно зачастую носят в себе черты программности и даже бывают программны абсолютно. Но если в инструментальном произведении есть сюжет, и содержание последовательно раскрывается, это обязательно программная музыка. Примеры можно найти и в национальных народных, и в классических сочинениях.

"Три кита" и национальные черты в программе

Также помогают понять, что такое программная музыка, определённые черты прикладных ("Полюшко", например), марша во всём жанровом разнообразии ("Марш Черномора" и "Марш деревянных солдатиков"), а также танца - народного, классического, фантастического. Это, с лёгкой руки Д.Б. Кабалевского, в музыке - "три кита", определяющие жанровую принадлежность.

Характерные черты национальной музыки тоже обычно служат программности музыкального произведения, задавая общую концепцию, темп, ритм сочинения ("Танец с саблями" Хачатуряна, например, "Два еврея..." и "Гопак" Мусоргского).

Пейзажная и сюжетная программность

Отображение одного или ряда образов, которые на протяжении всего сочинения не претерпевают изменений, - тоже программная музыка. Примеры произведений можно найти повсеместно: "В полях" Глиэра, "По скалам и фьордам" Грига и так далее. Сюда же можно отнести картины праздников и битв, музыкальные изображения пейзажные и портретные.

Даже одни и те же литературные сюжеты композиторы воплощают в музыке по-разному: например, "Ромео и Джульетта" Шекспира у Чайковского вылилась в увертюру, где программность обобщённая, а у Берлиоза - последовательная. И то, и другое, разумеется, программная музыка. Название чаще всего может рассматриваться как сюжетная программа, например "Битва гуннов" Листа по одноимённой фреске Каульбаха или его же этюды "Хоровод гномов" и "Шум леса". Иногда произведения скульптуры, архитектуры, живописи помогают понять, что такое программная музыка, поскольку участвуют в выборе изобразительных средств для музыкальной картины.

Вывод

Программность обогащает музыку новыми выразительными средствами, помогает в поиске новых форм произведения, дифференцирует жанры. Если композитор обращается к программе в своём сочинении, это сближает его слушателя с действительностью, одухотворяет быт, способствует постижению глубинных духовных начал. Однако, если программность довлеет над остальными задачами, то восприятие музыки заметно снижается, то есть слушателю необходим простор для собственного творческого восприятия.

Поэтому многие композиторы от программности пытались отказываться (в том числе Малер, Чайковский, Штруаус и другие), но, несмотря на это, полностью непрограммной музыки ни у одного из них не получилось. Единство музыки и конкретики её содержания никогда не является нерасторжимым и абсолютным. И чем более обобщённо отражается содержание, тем лучше для слушателя. Что такое программная музыка - станет понятно по малейшим штрихам развития музыкальной мысли: имеющий уши, так сказать, услышит, несмотря на то что единое определение и даже одинаковое понимание этого явления в музыке в среде музыкальных теоретиков пока не появилось.