Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Multiple Inheritance

All the classes you've seen so far have had only a single direct superclass. Common Lisp also supports multiple inheritance—a class can have multiple direct superclasses, inheriting applicable methods and slot specifiers from all of them.

Multiple inheritance doesn't dramatically change any of the mechanisms of inheritance I've discussed so far—every user-defined class already has multiple superclasses since they all extend STANDARD-OBJECT , which extends T , and so have at least two superclasses. The wrinkle that multiple inheritance adds is that a class can have more than one direct superclass. This complicates the notion of class specificity that's used both when building the effective methods for a generic function and when merging inherited slot specifiers.

That is, if classes could have only a single direct superclass, ordering classes by specificity would be trivial—a class and all its superclasses could be ordered in a straight line starting from the class itself, followed by its single direct superclass, followed by its direct superclass, all the way up to T . But when a class has multiple direct superclasses, those superclasses are typically not related to each other—indeed, if one was a subclass of another, you wouldn't need to subclass both directly. In that case, the rule that subclasses are more specific than their superclasses isn't enough to order all the superclasses. So Common Lisp uses a second rule that sorts unrelated superclasses according to the order they're listed in the DEFCLASS 's direct superclass list—classes earlier in the list are considered more specific than classes later in the list. This rule is admittedly somewhat arbitrary but does allow every class to have a linear class precedence list , which can be used to determine which superclasses should be considered more specific than others. Note, however, there's no global ordering of classes—each class has its own class precedence list, and the same classes can appear in different orders in different classes' class precedence lists.

To see how this works, let's add a class to the banking app: money-market-account. A money market account combines the characteristics of a checking account and a savings account: a customer can write checks against it, but it also earns interest. You might define it like this:

(defclass money-market-account (checking-account savings-account) ())

The class precedence list for money-market-accountwill be as follows:

(money-market-account

checking-account

savings-account

bank-account

standard-object

t)

Note how this list satisfies both rules: every class appears before all its superclasses, and checking-accountand savings-accountappear in the order specified in DEFCLASS .

This class defines no slots of its own but will inherit slots from both of its direct superclasses, including the slots they inherit from their superclasses. Likewise, any method that's applicable to any class in the class precedence list will be applicable to a money-market-accountobject. Because all slot specifiers for the same slot are merged, it doesn't matter that money-market-accountinherits the same slot specifiers from bank-accounttwice. [192] In other words, Common Lisp doesn't suffer from the diamond inheritance problem the way, say, C++ does. In C++, when one class subclasses two classes that both inherit a member variable from a common superclass, the bottom class inherits the member variable twice, leading to no end of confusion.

Multiple inheritance is easiest to understand when the different superclasses provide completely independent slots and behaviors. For instance, money-market-accountwill inherit slots and behaviors for dealing with checks from checking-accountand slots and behaviors for computing interest from savings-account. You don't have to worry about the class precedence list for methods and slots inherited from only one superclass or another.

However, it's also possible to inherit different methods for the same generic function from different superclasses. In that case, the class precedence list does come into play. For instance, suppose the banking application defined a generic function print-statementused to generate monthly statements. Presumably there would already be methods for print-statementspecialized on both checking-accountand savings-account. Both of these methods will be applicable to instances of money-market-account, but the one specialized on checking-accountwill be considered more specific than the one on savings-accountbecause checking-accountprecedes savings-accountin money-market-account's class precedence list.

Assuming the inherited methods are all primary methods and you haven't defined any other methods, the method specialized on checking-accountwill be used if you invoke print-statementon money-market-account. However, that won't necessarily give you the behavior you want since you probably want a money market account's statement to contain elements of both a checking account and a savings account statement.

You can modify the behavior of print-statementfor money-market-accounts in a couple ways. One straightforward way is to define a new primary method specialized on money-market-account. This gives you the most control over the new behavior but will probably require more new code than some other options I'll discuss in a moment. The problem is that while you can use CALL-NEXT-METHOD to call "up" to the next most specific method, namely, the one specialized on checking-account, there's no way to invoke a particular less-specific method, such as the one specialized on savings-account. Thus, if you want to be able to reuse the code that prints the savings-accountpart of the statement, you'll need to break that code into a separate function, which you can then call directly from both the money-market-accountand savings-account print-statementmethods.

Another possibility is to write the primary methods of all three classes to call CALL-NEXT-METHOD . Then the method specialized on money-market-accountwill use CALL-NEXT-METHOD to invoke the method specialized on checking-account. When that method calls CALL-NEXT-METHOD , it will result in running the savings-accountmethod since it will be the next most specific method according to money-market-account's class precedence list.

Of course, if you're going to rely on a coding convention—that every method calls CALL-NEXT-METHOD —to ensure all the applicable methods run at some point, you should think about using auxiliary methods instead. In this case, instead of defining primary methods on print-statementfor checking-accountand savings-account, you can define those methods as :aftermethods, defining a single primary method on bank-account. Then, print-statement, called on a money-market-account, will print a basic account statement, output by the primary method specialized on bank-account, followed by details output by the :aftermethods specialized on savings-accountand checking-account. And if you want to add details specific to money-market-accounts, you can define an :aftermethod specialized on money-market-account, which will run last of all.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x