Абстрактный класс в Smalltalk-Squeak. Что это? - PullRequest
2 голосов
/ 02 мая 2011

Если я правильно понял, что абстрактный класс - это класс, в котором есть хотя бы один абстрактный метод?

Теперь, если он абстрактный, значит, я не могу создавать экземпляры этого класса?

Например, упомянутое Abst - это имя абстрактного класса (поскольку оно содержит абстрактный метод), которое делает:

a := Abst new.

недопустимо и должно появиться ошибка / исключение?или проблема должна возникать здесь:

a := Abst class new.

?

ОБНОВЛЕНИЕ: Как предложено, я сделал следующий метод, который не позволит пользователю создавать экземпляры класса, но это нене работает:

makeAbstract: aClass    
    aClass compile: 'new
                ^ self subclassResponsibility'.

Ответы [ 5 ]

10 голосов
/ 02 мая 2011

Добро пожаловать в Smalltalk! Одной из замечательных особенностей Smalltalk является то, что он доверяет разработчикам, которые получают выгоду от силы, которая приходит с этим доверием. Поэтому такие слова, как «неспособность» и «незаконность», применяются редко.

Как и большинство других вещей, абстрактные классы в Smalltalk больше похожи на предложение / указатель, чем на жесткий закон. Два ключа, которые вы ищите - это #subclassResponsibility и #shouldNotImplement. Эти два метода являются подсказками для субклассеров, включать или не включать конкретный метод. Проверьте отправителей на наличие примеров на картинке (всегда отличная отправная точка для вопросов).

Поскольку "abstract", как описано выше, действительно относится к отдельным методам, ваши примеры не будут выдавать ошибку (если только не вызывается #subclassResponsibility или #shouldNotImplement из initialize.

Две маленькие вещи:

  • Имена классов пишутся с заглавной буквы Smalltalk, поэтому Abst, не abst.
  • Поиск в Google имеет большое значение. Три из четырех главных ссылок для "Smalltalk абстрактный класс" были все вам нужно ( этот в частности выглядел отлично).

ОБНОВЛЕНИЕ: если вы хотите дать понять пользователям вашего класса, что они не должны создавать экземпляры (как в вашем комментарии ниже), вы можете написать:

Abstract>>new
    ^ self subclassResponsibility.

Тогда «Абстрактное новое» -> ошибка, но «Абстрактное Подкласс новое» нормально.

Хотя до сих пор нет гарантии, что AbstractSubclass переопределил абстрактный метод (не #new, а тот, который заставил вас в первую очередь предотвратить использование экземпляров), на практике это не будет проблемой. Если вы действительно хотели, вы могли бы поставить проверку, может быть, в #initialize, чтобы убедиться, что ни один из методов экземпляра не вызывает #subclassResponsibility, но не беспокойтесь, если у вас нет веских причин.

ОБНОВЛЕНИЕ 2: Ваш вспомогательный метод для создания абстрактного класса будет:

Class>>makeAbstract

    self class compile: 'new
                ^ self subclassResponsibility'.
2 голосов
/ 02 мая 2011

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

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

Абстрактные методы в Smalltalk имеют особую реализацию, которая делает их и класс абстрактными:

method
    self subclassResponsibility

Это также означает, что подклассы должны переопределять этот метод ипредоставить конкретную реализацию.

Если вы видите ошибку, касающуюся subclassResponsibility, ваш код либо вызвал метод для абстрактного класса, либо ваш подкласс не предоставил реализацию для метода.

2 голосов
/ 02 мая 2011

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

1 голос
/ 29 ноября 2012

(фиксированный) «new-blocker» вносит небольшое неудобство для своих конкретных подклассов: им придется переопределять new и не может использовать какие-либо унаследованные суперклассы ' new функциональность.Вы можете обойти это с небольшим предохранителем, который проверяет, действительно ли это абстрактный класс, который пытается создать экземпляр:

AbstractClass class >> new
    self == AbstractClass ifTrue:[
        ^ self abstractClassInstantiationError
    ].
    ^ super new

(обратите внимание на сравнение идентичности здесь, которое работает, даже если вы сложили несколькоабстрактные классы друг на друга)

1 голос
/ 02 мая 2011

Я рекомендую вам прочитать книгу Pharo By Example.Вы можете найти его здесь: http://pharobyexample.org/, и вы найдете много интересного.Это открытая книга, бесплатно, и вы можете скачать PDF.Фактически, то, что вы спрашиваете, объясняется в главе 5, стр. 88.

...