2015-09-28 1 views
2

Мне нужно распечатать обычный отчет и пакетный отчет. Я использую библиотеку podofo. Я планирую использовать отдельные классы для каждого отчета, но каждому классу будут нужны некоторые общие функции ниже (прямо сейчас в одном классе в другом проекте).Является ли хорошей практикой перемещение общего кода в базовый класс при условии, что его нет?

int CPdfBatchReport::CalculateMaxRowsInEmptyPage(void) 
{ 
    int rows = MaxPageHeight/PDF_TABLE_STANDARD_ROW_HEIGHT; 

    // because the first will always be the column header in every page, we substrct 1 to account for that 
    rows = rows - 1; 

    return rows; 
} 

// Calculates the max rows in current page. The current page is determined 
// by the current x, y position 
int CPdfBatchReport::CalculateMaxRowsInCurrentPage(void) 
{ 
    float AvailablePageHeight = pPage->GetPageSize().GetHeight() - PDF_BOTTOM_MARGIN - y; 

    int rows = AvailablePageHeight/PDF_TABLE_STANDARD_ROW_HEIGHT; 

    // because the first will always be the column header in every page, we substrct 1 to account for that 
    rows = rows - 1; 

    return rows; 
} 


void CPdfBatchReport::StartPage(void) 
{ 
    x = PDF_LEFT_RIGHT_MARGIN; 
    y = PDF_TOP_MARGIN; 
} 

Имеет ли смысл создавать базовый класс с помощью этого общего кода и выполнять фактическую печать в производном классе? Это хорошая практика?

Поэтому в основном я буду иметь базовый класс сказать PrintBase с вышеуказанными функциями в нем и двух производных классов от него PrintBatchReport и PrintItemReport, которые на самом деле использовать эти функции.

ответ

6

Да, абсолютно хорошая идея разместить общий код в базовом классе. «Не повторяй себя» - сухой - это хороший стиль программирования. Избегайте программирования копирования.

Единственный раз, когда вы не хотите, чтобы содержимое в базовом классе было, когда это класс интерфейса. Но, похоже, это не так в этой ситуации.

+0

Спасибо, но я думал, что сделаю базовый класс интерфейса. Подобно методу 'print()' в базовом классе, можно печатать пакетный отчет или простой отчет. По классу интерфейса я имею в виду, что он может иметь чистые виртуальные и регулярные функции, почему это плохо? Похоже, что все будет хорошо! – zar

+1

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

+0

«состав над наследством», я думал – ggrr

1

Да, абсолютно хорошая идея разместить общий код в базовом классе.

Я хотел бы расширить ответ на @Mats. Это действительно хорошая идея, поскольку весь код, который вы извлекаете в базовый класс, следует принципу единой ответственности. Избегайте слепо использования наследования для общего извлечения кода. Объектно-ориентированное программирование - это нечто большее.

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

1

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

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

Смежные вопросы