Из вашего вопроса мне не ясно, знаете ли вы уже VBA и / или OO, и просто спрашиваете, как использовать объектно-ориентированные функции VBA. Если вы новичок как в VBA, так и в OO, см. Ниже несколько соображений о том, почему VBA не очень хороший инструмент для изучения OOD / OOP.
Чтобы ответить на общую часть вашего вопроса, классы VBA могут реализовать интерфейсы. Вот как вы выражаете наследование интерфейса (отношение "is-a") в VBA. Не существует прямого способа выразить наследование реализации в VBA. Вместо этого, чтобы один класс наследовал реализацию другого, у вас есть первый, реализующий интерфейс второго, содержащий экземпляр второго, а затем делегирующий вызовы этому экземпляру. Смотрите этот ответ для более:
VBA наследование, аналог супер
Там есть ссылка, которую я здесь повторю, на Руководство для программиста Visual Studio 6.0:
http://msdn.microsoft.com/en-us/library/aa240846(v=VS.60).aspx
Это короткое вступление так же хорошо, как и любое другое из «пути VBA» ООП (хотя оно написано для VB6, а не VBA).
Теперь к вашему конкретному вопросу о дизайне: «как содержащийся объект может собирать свои входные данные, которые доступны только в объектах-контейнерах».
Вам нужно подумать о том, что вы на самом деле моделируете здесь. Независимо от того, как вы его реализуете, «калькулятор скорости» должен знать только об очень специфическом наборе входных данных, а не обо всем внутреннем состоянии любого транспортного средства, которое его использует. В VBA, как вы заметили, нет статических классов. Вместо этого используйте обычный кодовый модуль и имейте функцию, которую вы вызываете из класса вашего автомобиля:
Public Function calcSpeed(temp, windspeed, rpm)
'do calc based only on parms passed in...
End Function
Если ему нужно принять zillion параметров, потому что так работает расчет, пусть будет так. Не пытайтесь это скрыть. Конечно, вы можете обернуть их в Type
или в классе, если их слишком много.
Теперь, каждый ли автомобиль различного типа вычисляет скорость одинаковым образом из одного и того же набора параметров состояния? Если так, то имейте свойство или метод speed
, который реализуется вашим классом «базового транспортного средства», и вызывайте calcSpeed
оттуда.
Но, возможно, это тот случай, когда разные типы транспортных средств имеют разные параметры состояния, или используют разные методы расчета, или же расчеты одинаковы, но не каждый тип автомобиля предоставляет каждый параметр. В этом случае поместите метод speed
в базовом транспортном средстве interface , но "переопределите" его, как необходимо при реализации каждого подкласса. (Может быть, тогда calcSpeed
будет слишком упрощенным, и вы получите библиотеку вспомогательных функций для расчета скорости.)
Одна вещь, которую я бы не сделал , это общий класс SpeedCalculator, который принимает аргумент Vehicle, а затем запрашивает его для определения его состояния для выполнения вычисления. Причина не очень хорошо выражена в этих классических статьях:
http://media.pragprog.com/articles/may_04_oo1.pdf
http://pragprog.com/articles/tell-dont-ask
http://www.cmcrossroads.com/bradapp/docs/demeter-intro.html
Также есть это:
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
цитата, которая мне нравится:
Итак, что же такого плохого в этом коде
(помимо того, что ужасно надуманный
пример)? Хорошо, давайте переведем то, что
код на самом деле делает в
реальный язык:
Видимо, когда
газетчик останавливается и требует оплаты,
клиент просто собирается повернуть
вокруг, пусть газетчик возьмет
кошелек из его заднего кармана, и
достать два доллара.
Я не знаю о
Вы, но я редко позволяю кому-то справиться
мой бумажник. Есть ряд
проблемы "реального мира" с этим, а не
упомянуть мы доверяем газетчику
честно говоря и просто вынуть то, что
он должен. Если наш будущий объект кошелек
держит кредитные карты, разносчик газет
доступ к тем тоже ... но основной
Проблема в том, что «разносчик газет
подвергается большему количеству информации, чем он
должно быть".
Это важно
концепция ... Класс «Paperboy» сейчас
«знает», что у клиента есть
Вашингтони может манипулировать этим. Когда мы
скомпилируйте класс Paperboy, он будет
нужен класс клиента и кошелек
учебный класс. Эти три класса сейчас
'тесно связаны'. Если мы изменим
Класс кошелька, нам, возможно, придется сделать
изменения в обоих других классах.
ДОБАВЛЕНО КАК ОБЕЩАНО В КОММЕНТАРИИ:
Дело не в том, что вы не могли легко получить экземпляр класса Speedometer
, содержащийся в ваших Vehicle
s. (Мой пример простой функции может быть слишком упрощенным. Возможно, вам нужен класс для моделирования других вещей, связанных со спидометрами - они имеют массу, занимают пространство и т. Д.) Это то, как эти два класса зависят друг от друга. В этом примере Vehicle
нужно знать о Speedometer
. Но почему обратное должно быть правдой? Если Speedometer
принимает Vehicle
в качестве параметра, а затем запрашивает его о конкретных вещах, которые необходимо знать для вычисления скорости, код, безусловно, будет работать . Однако вы связали Speedometer
с Vehicle
более плотно, чем необходимо.
Одна из причин использования ОО-подхода в первую очередь заключается в том, что он позволяет вам быть более точным в отношении того, как концепции связаны друг с другом. Лучше иметь Vehicle
сказать Speedometer
: «Вот некоторые факты о мире. Верните мне скорость», а не «Вот я, Me
, Vehicle
, который вас окружает. Спросите». мне все, что вам нужно обо всем, что связано со мной, а затем верните мне скорость. " (Обратите внимание, что независимо от того, являются ли «факты о мире» необработанными темпом, скоростью ветра и т. Д., Или экземпляром какого-либо типа / класса SpeedometerInput
, проблема не в этом. Дело в том, что спидометрам не нужно знать все о транспортных средствах. )
Использование самого точного интерфейса, с которым вы можете обойтись, не делает ничего сложного в простом примере. Но это становится огромным, когда складывается из-за многих дизайнерских решений.
Наконец, если у вас есть выбор, я бы не использовал бы VBA в качестве средства для изучения объектно-ориентированного проектирования или программирования. Вы можете сделать «ООП» в VBA, но специфичным для Microsoft / COM способом, который буквально является пережитком середины 1990-х годов. Вы можете просмотреть стекировочный поток для множества примеров того, что обычно делается на языках программирования ОО (и с их намного лучшими библиотеками), которые являются громоздкими и хитрыми в VBA. Вот несколько советов, которые я либо спрашивал, либо отвечал:
Есть ли способ перегрузить процедуру конструктора / инициализации для класса в VBA?
Можно ли написать тест на равенство для класса VBA с закрытыми членами, не раскрывая знания о существовании этих закрытых членов?
Ограничение типа в коллекции внутри модуля класса
Excel-VBA - Есть ли что-то похожее на контейнер Javas Set в VBA?
Итак, если вы не обязаны учиться с VBA, потому что вы не можете установить на свой компьютер ничего, кроме MS Office, или вы планируете много работать с VBA, потому что вы используете Excel, Access и т. Д. И есть некоторые проблемы, где ООП может помочь, я бы посмотрел в другом месте. Python , .NET или Java - все они доступны бесплатно в Windows и имеют массу ресурсов для начинающих.