В качестве последнего примера наследования дополним приложение текстового запроса из раздела 12.3. Написанные в этом разделе классы позволят искать вхождения данного слова в файле. Дополним эту систему возможностью создавать более сложные запросы. В этих примерах запросы будут выполняться к тексту следующей истории:
Alice Emma has long flowing red hair.
Her Daddy says when the wind blows
through her hair, it looks almost alive,
like a fiery bird in flight.
A beautiful fiery bird, he tells her,
magical but untamed.
"Daddy, shush, there is no such thing,"
she tells him, at the same time wanting
him to tell her more.
Shyly, she asks, "I mean, Daddy, is there?"
Система должна поддерживать следующие запросы.
• Запросы слов находят все строки, соответствующие заданной строке:
Executing Query for: Daddy
Daddy occurs 3 times
(line 2) Her Daddy says when the wind blows
(line 7) "Daddy, shush, there is no such thing,"
(line 10) Shyly, she asks, "I mean, Daddy, is there?"
• Инверсный запрос с использованием оператора ~
возвращает строки, которые не содержат заданную строку:
Executing Query for: ~(Alice)
~(Alice) occurs 9 times
(line 2) Her Daddy says when the wind blows
(line 3) through her hair, it looks almost alive,
(line 4) like a fiery bird in flight.
...
• Запросы ИЛИ с использованием оператора |
возвращают строки, содержащие любую из двух заданных строк:
Executing Query for: (hair | Alice)
(hair | Alice) occurs 2 times
(line 1) Alice Emma has long flowing red hair,
(line 3) through her hair, it looks almost alive,
• Запросы И с использованием оператора &
возвращают строки, содержащие обе заданные строки:
Executing query for: (hair & Alice)
(hair & Alice) occurs 1 time
(line 1) Alice Emma has long flowing red hair.
Кроме того, нужна возможность объединить эти операторы так
fiery & bird | wind
Для обработки составных выражений, таких как в этом примере, будут использованы обычные правила приоритета С++ (см. раздел 4.1.2). Таким образом, этому запросу соответствует строка, в которой присутствуют слова fiery
и bird
или слово wind
:
Executing Query for: ((fiery & bird) | wind)
((fiery & bird) | wind) occurs 3 times
(line 2) Her Daddy says when the wind blows
(line 4) like a fiery bird in flight.
(line 5) A beautiful fiery bird, he tells her,
В отображаемом результате для указания способа интерпретации запроса используются круглые скобки. Подобно первоначальной реализации, система не должна отображать одинаковые строки несколько раз.
15.9.1. Объектно-ориентированное решение
Для представления запросов на поиск слов вполне логично было бы использовать класс TextQuery
(см. раздел 12.3.2), а другие классы запросов можно было бы получить как производные от этого класса.
Однако такой подход неверен. Концептуально инверсный запрос не является разновидностью запроса на поиск слова. Инверсный запрос — это скорее запрос типа "имеет" (запрос на поиск слова или любой другой тип запроса), результат которого интерпретируется негативно.
Исходя из этого можно сделать вывод, что разные виды запросов следует оформить как независимые классы, которые совместно используют общий базовый класс:
WordQuery //
NotQuery //
OrQuery //
AndQuery //
Эти классы будет иметь только две функции.
• Функция eval()
, получающая объект класса TextQuery
и возвращающая объект класса QueryResult
. Для поиска запрошенной строки функция eval()
будет использовать переданный объект класса TextQuery
.