如何在 Excel VBA 中使用工具

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19373081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 16:55:28  来源:igfitidea点击:

How to use the Implements in Excel VBA

excelvbaexcel-vbainterface

提问by Zigu

I'm trying to implement some shapes for an engineering project and abstract it out for some common functions so that I can have a generalized program.

我正在尝试为工程项目实现一些形状,并将其抽象为一些常用功能,以便我可以拥有一个通用程序。

What I'm trying to do is have an interface called cShapeand have cRectangleand cCircleimplement cShape

我正在试图做的是有一个名为接口cShape,并具有cRectanglecCircle实施cShape

My code is below:

我的代码如下:

cShapeinterface

cShape界面

Option Explicit

Public Function getArea()
End Function

Public Function getInertiaX()
End Function

Public Function getInertiaY()
End Function

Public Function toString()
End Function

cRectangleclass

cRectangle班级

Option Explicit
Implements cShape

Public myLength As Double ''going to treat length as d
Public myWidth As Double ''going to treat width as b

Public Function getArea()
    getArea = myLength * myWidth
End Function

Public Function getInertiaX()
    getInertiaX = (myWidth) * (myLength ^ 3)
End Function

Public Function getInertiaY()
    getInertiaY = (myLength) * (myWidth ^ 3)
End Function

Public Function toString()
    toString = "This is a " & myWidth & " by " & myLength & " rectangle."
End Function

cCircleclass

cCircle班级

Option Explicit
Implements cShape

Public myRadius As Double

Public Function getDiameter()
    getDiameter = 2 * myRadius
End Function

Public Function getArea()
    getArea = Application.WorksheetFunction.Pi() * (myRadius ^ 2)
End Function

''Inertia around the X axis
Public Function getInertiaX()
    getInertiaX = Application.WorksheetFunction.Pi() / 4 * (myRadius ^ 4)
End Function

''Inertia around the Y axis
''Ix = Iy in a circle, technically should use same function
Public Function getInertiaY()
    getInertiaY = Application.WorksheetFunction.Pi() / 4 * (myRadius ^ 4)
End Function

Public Function toString()
    toString = "This is a radius " & myRadius & " circle."
End Function

The problem is that whenever I run my test cases, it comes up with the following error:

问题是,每当我运行测试用例时,都会出现以下错误:

Compile Error:

Object module needs to implement '~' for interface '~'

编译错误:

对象模块需要为接口'~'实现'~'

回答by

This is an esoteric OOP concept and there's a little more you need to do and understand to use a custom collection of shapes.

这是一个深奥的 OOP 概念,您需要做更多的事情并了解使用自定义形状集合。

You may first want to go through this answerto get a general understanding of classes and interfaces in VBA.

您可能首先想要this answer了解 VBA 中的类和接口。



请按照以下说明操作

First open Notepad and copy-paste the below code

首先打开记事本并复制粘贴以下代码

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1
END
Attribute VB_Name = "ShapesCollection"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Dim myCustomCollection As Collection

Private Sub Class_Initialize()
    Set myCustomCollection = New Collection
End Sub

Public Sub Class_Terminate()
    Set myCustomCollection = Nothing
End Sub

Public Sub Add(ByVal Item As Object)
    myCustomCollection.Add Item
End Sub

Public Sub AddShapes(ParamArray arr() As Variant)
    Dim v As Variant
    For Each v In arr
        myCustomCollection.Add v
    Next
End Sub

Public Sub Remove(index As Variant)
    myCustomCollection.Remove (index)
End Sub

Public Property Get Item(index As Long) As cShape
    Set Item = myCustomCollection.Item(index)
End Property

Public Property Get Count() As Long
    Count = myCustomCollection.Count
End Property

Public Property Get NewEnum() As IUnknown
    Attribute NewEnum.VB_UserMemId = -4
    Attribute NewEnum.VB_MemberFlags = "40"
    Set NewEnum = myCustomCollection.[_NewEnum]
End Property

Save the file as ShapesCollection.clsto your desktop.

将文件另存为ShapesCollection.cls桌面。

Make sure you are saving it with the*.clsextension and not ShapesCollection.cls.txt

确保您使用扩展名保存它*.cls而不是ShapesCollection.cls.txt

Now open you Excel file, go to VBE ALT+F11and right click in the Project Explorer. Select Import Filefrom the drop-down menu and navigate to the file.

现在打开您的 Excel 文件,转到 VBE ALT+F11并右键单击Project Explorer. 选择Import File从下拉菜单,然后导航到该文件。

enter image description here

在此处输入图片说明

NB: You needed to save the code in a .clsfile first and then import it because VBEditor does not allow you to use Attributes. The attributes allow you to specify the default member in the iteration and use the for each loop on custom collection classes

注意:您需要.cls先将代码保存在文件中,然后再导入,因为 VBEditor 不允许您使用属性。这些属性允许您在迭代中指定默认成员并在自定义集合类上使用 for each 循环

See more:

查看更多:

Now Insert 3 class modules. Rename accordingly and copy-paste the code

现在插入 3 个类模块。相应地重命名并复制粘贴代码

cShapethis is your Interface

cShape这是你的界面

Public Function GetArea() As Double
End Function

Public Function GetInertiaX() As Double
End Function

Public Function GetInertiaY() As Double
End Function

Public Function ToString() As String
End Function

cCircle

Option Explicit

Implements cShape

Public Radius As Double

Public Function GetDiameter() As Double
    GetDiameter = 2 * Radius
End Function

Public Function GetArea() As Double
    GetArea = Application.WorksheetFunction.Pi() * (Radius ^ 2)
End Function

''Inertia around the X axis
Public Function GetInertiaX() As Double
    GetInertiaX = Application.WorksheetFunction.Pi() / 4 * (Radius ^ 4)
End Function

''Inertia around the Y axis
''Ix = Iy in a circle, technically should use same function
Public Function GetInertiaY() As Double
    GetInertiaY = Application.WorksheetFunction.Pi() / 4 * (Radius ^ 4)
End Function

Public Function ToString() As String
    ToString = "This is a radius " & Radius & " circle."
End Function

'interface functions
Private Function cShape_getArea() As Double
    cShape_getArea = GetArea
End Function

Private Function cShape_getInertiaX() As Double
    cShape_getInertiaX = GetInertiaX
End Function

Private Function cShape_getInertiaY() As Double
    cShape_getInertiaY = GetInertiaY
End Function

Private Function cShape_toString() As String
    cShape_toString = ToString
End Function

cRectangle

矩形

Option Explicit

Implements cShape

Public Length As Double ''going to treat length as d
Public Width As Double ''going to treat width as b

Public Function GetArea() As Double
    GetArea = Length * Width
End Function

Public Function GetInertiaX() As Double
    GetInertiaX = (Width) * (Length ^ 3)
End Function

Public Function GetInertiaY() As Double
    GetInertiaY = (Length) * (Width ^ 3)
End Function

Public Function ToString() As String
    ToString = "This is a " & Width & " by " & Length & " rectangle."
End Function

' interface properties
Private Function cShape_getArea() As Double
    cShape_getArea = GetArea
End Function

Private Function cShape_getInertiaX() As Double
    cShape_getInertiaX = GetInertiaX
End Function

Private Function cShape_getInertiaY() As Double
    cShape_getInertiaY = GetInertiaY
End Function

Private Function cShape_toString() As String
    cShape_toString = ToString
End Function

You need to Inserta standard Modulenow and copy-paste the below code

您现在需要Insert一个标准Module并复制粘贴以下代码

Module1

模块1

Option Explicit

Sub Main()

    Dim shapes As ShapesCollection
    Set shapes = New ShapesCollection

    AddShapesTo shapes

    Dim iShape As cShape
    For Each iShape In shapes
        'If TypeOf iShape Is cCircle Then
            Debug.Print iShape.ToString, "Area: " & iShape.GetArea, "InertiaX: " & iShape.GetInertiaX, "InertiaY:" & iShape.GetInertiaY
        'End If
    Next

End Sub


Private Sub AddShapesTo(ByRef shapes As ShapesCollection)

    Dim c1 As New cCircle
    c1.Radius = 10.5

    Dim c2 As New cCircle
    c2.Radius = 78.265

    Dim r1 As New cRectangle
    r1.Length = 80.87
    r1.Width = 20.6

    Dim r2 As New cRectangle
    r2.Length = 12.14
    r2.Width = 40.74

    shapes.AddShapes c1, c2, r1, r2
End Sub

Run the MainSub and check out the results in the Immediate WindowCTRL+G

运行MainSub 并查看+ 中的结果Immediate WindowCTRLG

enter image description here

在此处输入图片说明



Comments and explanation:

评论和解释:

In your ShapesCollectionclass module there are 2 subs for adding items to the collection.

在您的ShapesCollection类模块中有 2 个用于向集合添加项目的子项。

The first method Public Sub Add(ByVal Item As Object)simply takes a class instance and adds it to the collection. You can use it in your Module1like this

第一种方法Public Sub Add(ByVal Item As Object)只是获取一个类实例并将其添加到集合中。你可以Module1像这样使用它

Dim c1 As New cCircle
shapes.Add c1

The Public Sub AddShapes(ParamArray arr() As Variant)allows you to add multiple objects at the same time separating them by a ,comma in the same exact way as the AddShapes()Sub does.

Public Sub AddShapes(ParamArray arr() As Variant)允许你通过添加在同一时间多个对象将它们分开,逗号在完全相同的方式与AddShapes()子一样。

It's quite a better design than adding each object separately, but it's up to you which one you are going to go for.

与单独添加每个对象相比,这是一种更好的设计,但是您要选择哪个对象取决于您。

Notice how I have commented out some code in the loop

注意我是如何注释掉循环中的一些代码的

Dim iShape As cShape
For Each iShape In shapes
    'If TypeOf iShape Is cCircle Then
        Debug.Print iShape.ToString, "Area: " & iShape.GetArea, "InertiaX: " & iShape.GetInertiaX, "InertiaY:" & iShape.GetInertiaY
    'End If
Next

If you remove comments from the 'Ifand 'End Iflines you will be able to print only the cCircleobjects. This would be really useful if you could use delegates in VBA but you can't so I have shown you the other way to print only one type of objects. You can obviously modify the Ifstatement to suit your needs or simply print out all objects. Again, it is up to you how you are going to handle your data :)

如果您从'If'End If行中删除注释,您将只能打印cCircle对象。如果您可以在 VBA 中使用委托,这将非常有用,但您不能,所以我向您展示了仅打印一种类型对象的另一种方式。您显然可以修改If语句以满足您的需要或简单地打印出所有对象。同样,您将如何处理数据取决于您:)

回答by Trace

Here are some theoretical and practical contributions to the answers given, in case people arrive here who wonder what implements / interfaces are about.

以下是对给出的答案的一些理论和实践贡献,以防人们来到这里想知道实现/接口是关于什么的。

As we know, VBA doesn't support inheritance, hence we might almost blindly use interfaces to implement common properties/behaviour across different classes.
Still, I think that it is useful to describe what the conceptual difference is between the two to see why it matters later on.

众所周知,VBA 不支持继承,因此我们可能几乎盲目地使用接口来实现跨不同类的公共属性/行为。
尽管如此,我认为描述两者之间的概念差异是有用的,以便稍后了解为什么它很重要。

  • Inheritance: defines an is-a relationship (a square is-a shape);
  • Interfaces: define a must-do relationship (a typical example is the drawableinterface that prescribes that drawable object must implement the method draw). This means that classes originating from different root classes can implement common behaviour.
  • 继承:定义一个is-a关系(方形is-a形状);
  • 接口:定义一个必须做的关系(一个典型的例子是drawable规定可绘制对象必须实现方法的接口draw)。这意味着源自不同根类的类可以实现共同的行为。

Inheritance means that a baseclass (some physical or conceptual archetype) is extended, whereas interfaces implementa set of properties/methods that define a certain behaviour.
As such, one would say that Shapeis a base class from which all other shapes inherit, one that may implement the drawableinterface to make all shapes drawable. This interface would be a contract that guarantees that every Shape has a drawmethod, specifying how/where a shape should be drawn: a circle may - or may not - be drawn differently from a square.

继承意味着基类(一些物理或概念原型)被扩展,而接口实现了一组定义特定行为的属性/方法。
因此,有人会说它Shape是所有其他形状继承的基类,可以实现drawable接口以使所有形状均可绘制。这个接口将是一个契约,保证每个 Shape 都有一个draw方法,指定应该如何/在何处绘制形状:圆形可以 - 也可以不 - 与正方形不同。

class IDrawable:

类 IDrawable:

'IDrawable interface, defining what methods drawable objects have access to
Public Function draw()
End Function

Since VBA doesn't support inheritance, we are automatically forced to opt for creating an interface IShape that guarantees certain properties/behaviour to be implemented by the generic shapes (square, circle, etc), rather than creating an abstract Shape baseclass from which we can extend.

由于 VBA 不支持继承,我们被迫自动选择创建一个接口 IShape 来保证某些属性/行为由通用形状(正方形、圆形等)实现,而不是创建一个抽象的 Shape 基类,我们从中可以可以延长。

class IShape:

IShape 类:

'Get the area of a shape
Public Function getArea() As Double
End Function

The part where we get in trouble is when we want to make every Shape drawable.
Unfortunately, since IShape is an interface and not a base class in VBA, we cannot implement the drawable interface in the base class. It appears that VBA does not allow us to have one interface implement another; after having tested this, the compiler doesn't seem to provide the desired behaviour. In other words, we cannot implement IDrawable within IShape, and expect instances of IShape to be forced to implement IDrawable methods because of this.
We are forced to implement this interface to every generic shape class that implements the IShape interface, and luckily VBA allows multiple interfaces to be implemented.

我们遇到麻烦的部分是当我们想让每个 Shape 都可以绘制时。
不幸的是,由于 IShape 是一个接口而不是 VBA 中的基类,我们无法在基类中实现可绘制接口。VBA 似乎不允许我们让一个接口实现另一个接口;对此进行测试后,编译器似乎没有提供所需的行为。换句话说,我们不能在 IShape 中实现 IDrawable,并期望 IShape 的实例因此被强制实现 IDrawable 方法。
我们被迫为每个实现 IShape 接口的通用形状类实现这个接口,幸运的是 VBA 允许实现多个接口。

class cSquare:

cSquare 类:

Option Explicit

Implements iShape
Implements IDrawable

Private pWidth          As Double
Private pHeight         As Double
Private pPositionX      As Double
Private pPositionY      As Double

Public Function iShape_getArea() As Double
    getArea = pWidth * pHeight
End Function

Public Function IDrawable_draw()
    debug.print "Draw square method"
End Function

'Getters and setters

The part that follows now is where the typical use / benefits of an interface come into play.

接下来的部分是界面的典型用途/好处发挥作用的地方。

Let's start off our code by writing a factory that returns a new square. (This is just a workaround for our inability to send arguments directly to the constructor):

让我们通过编写一个返回新正方形的工厂来开始我们的代码。(这只是我们无法将参数直接发送到构造函数的一种解决方法):

module mFactory:

模块 mFactory:

Public Function createSquare(width, height, x, y) As cSquare

    Dim square As New cSquare

    square.width = width
    square.height = height
    square.positionX = x
    square.positionY = y

    Set createSquare = square

End Function

Our main code will use the factory to create a new Square:

我们的主要代码将使用工厂来创建一个新的 Square:

Dim square          As cSquare

Set square = mFactory.createSquare(5, 5, 0, 0)

When you look at the methods that you have at your disposal, you'll notice that you logically get access to all the methods that are defined on the cSquare class:

当您查看您可以使用的方法时,您会注意到您在逻辑上可以访问 cSquare 类中定义的所有方法:

enter image description here

在此处输入图片说明

We'll see later on why this is relevant.

我们稍后会看到为什么这是相关的。

Now you should wonder what will happen if you really want to create a collection of drawable objects. Your app could happen to contain objects that aren't shapes, but that are yet drawable. Theoretically, nothing prevents you from having an IComputer interface that can be drawn (may be some clipart or whatever).
The reason why you might want to have a collection of drawable objects, is because you may want to render them in a loop at a certain point in the app lifecycle.

现在你应该想知道如果你真的想创建一个可绘制对象的集合会发生什么。您的应用程序可能碰巧包含不是形状但仍可绘制的对象。从理论上讲,没有什么可以阻止您拥有可以绘制的 IComputer 界面(可能是一些剪贴画或其他什么)。
您可能希望拥有一组可绘制对象的原因是,您可能希望在应用程序生命周期的某个时刻循环渲染它们。

In this case I will write a decorator class that wraps a collection (we'll see why). class collDrawables:

在这种情况下,我将编写一个包装集合的装饰器类(我们将看到原因)。类collDrawables:

Option Explicit

Private pSize As Integer
Private pDrawables As Collection

'constructor
Public Sub class_initialize()
    Set pDrawables = New Collection
End Sub

'Adds a drawable to the collection
Public Sub add(cDrawable As IDrawable)
    pDrawables.add cDrawable

    'Increase collection size
    pSize = pSize + 1

End Sub

The decorator allows you to add some convenience methods that native vba collections don't provide, but the actual point here is that the collection will only accept objects that are drawable (implement the IDrawable interface). If we would try to add an object that is not drawable, a type mismatch would be thrown (only drawable objects allowed!).

装饰器允许您添加一些本机 vba 集合不提供的便利方法,但这里的实际要点是该集合仅接受可绘制的对象(实现 IDrawable 接口)。如果我们尝试添加不可绘制的对象,则会抛出类型不匹配(仅允许可绘制对象!)。

So we might want to loop over a collection of drawable objects to render them. Allowing a non-drawable object into the collection would result in a bug. A render loop could look like this:

所以我们可能想要遍历一组可绘制对象来渲染它们。允许不可绘制对象进入集合会导致错误。渲染循环可能如下所示:

Option Explicit

选项显式

Public Sub app()

    Dim obj             As IDrawable
    Dim square_1        As IDrawable
    Dim square_2        As IDrawable
    Dim computer        As IDrawable
    Dim person          as cPerson 'Not drawable(!) 
    Dim collRender      As New collDrawables

    Set square_1 = mFactory.createSquare(5, 5, 0, 0)
    Set square_2 = mFactory.createSquare(10, 5, 0, 0)
    Set computer = mFactory.createComputer(20, 20)

    collRender.add square_1
    collRender.add square_2
    collRender.add computer

    'This is the loop, we are sure that all objects are drawable! 
    For Each obj In collRender.getDrawables
        obj.draw
    Next obj

End Sub

Note that the above code adds a lot of transparency: we declared the objects as IDrawable, which makes it transparent that the loop will never fail, since the draw method is available on all objects within the collection.
If we would try to add a Person to the collection, it would throw a type mismatch if this Person class did not implement the drawable interface.

请注意,上面的代码增加了很多透明度:我们将对象声明为 IDrawable,这使得循环永远不会失败是透明的,因为 draw 方法对集合中的所有对象都可用。
如果我们尝试将一个 Person 添加到集合中,如果这个 Person 类没有实现 drawable 接口,它将抛出类型不匹配。

But perhaps the most relevant reason why declaring an object as an interface is important, is because we only want to expose the methods that were defined in the interface, and not those public methods that were defined on the individual classes as we've seen before.

但也许将对象声明为接口很重要的最相关的原因是因为我们只想公开在接口中定义的方法,而不是像我们之前看到的那样在各个类中定义的公共方法.

Dim square_1        As IDrawable 

enter image description here

在此处输入图片说明

Not only are we certain that square_1 has a drawmethod, but it also ensure that onlymethods defined by IDrawable get exposed.
For a square, the benefit of this might not be immediately clear, but let's have a look at an analogy from the Java collections framework that is much clearer.

我们不仅确定 square_1 有一个draw方法,而且还确保只有IDrawable 定义的方法才会公开。
对于一个正方形来说,这样做的好处可能不是很明显,但让我们看一下 Java 集合框架中的一个类比,这个类比更清晰。

Imagine that you have a generic interface called IListthat defines a set of methods applicable on different types of lists. Each type of list is a specific class that implements the IList interface, defining their own behaviour, and possibly adding more methods of their own on top.

想象一下,您有一个通用接口IList,它定义了一组适用于不同类型列表的方法。每种类型的列表都是一个特定的类,它实现了 IList 接口,定义了它们自己的行为,并可能在顶部添加更多自己的方法。

We declare the list as follows:

我们声明列表如下:

dim myList as IList 'Declare as the interface! 

set myList = new ArrayList 'Implements the interface of IList only, ArrayList allows random (index-based) access 

In the above code, declaring the list as IList ensures that you won't use ArrayList-specific methods, but only methods that are prescribed by the interface. Imagine that you declared the list as follows:

在上面的代码中,将列表声明为 IList 可确保您不会使用特定于 ArrayList 的方法,而只会使用接口规定的方法。假设您按如下方式声明列表:

dim myList as ArrayList 'We don't want this

You will have access to the public methods that are specifically defined on the ArrayList class. Sometimes this might be desired, but often we just want to take benefit of the internal class behaviour, and not defined by the class specific public methods.
The benefit becomes clear if we use this ArrayList 50 more times in our code, and suddenly we find out that we're better off using a LinkedList (which allows specific internal behaviour related to this type of List).

您将可以访问在 ArrayList 类上专门定义的公共方法。有时这可能是需要的,但通常我们只想利用内部类行为,而不是由类特定的公共方法定义。
如果我们在代码中多使用这个 ArrayList 50 次,好处就会变得很明显,然后我们突然发现最好使用 LinkedList(它允许与这种类型的 List 相关的特定内部行为)。

If we complied to the interface, we can change the line:

如果我们遵守界面,我们可以改变这一行:

set myList = new ArrayList

to:

到:

set myList = new LinkedList 

and none of the other code will break as the interface makes sure that the contract is fulfilled, ie. only public methods defined on IList are used, so the different types of lists are swappable over time.

并且其他代码都不会中断,因为接口确保合同得到履行,即。仅使用 IList 上定义的公共方法,因此不同类型的列表可以随时间交换。

A final thing (perhaps lesser known behaviour in VBA) is that you can give an interface a default implementation

最后一件事(可能是 VBA 中鲜为人知的行为)是您可以为接口提供默认实现

We can define an interface in the following way:

我们可以通过以下方式定义接口:

IDrawable:

可绘制:

Public Function draw()
    Debug.Print "Draw interface method"
End Function

and a class that implements the draw method as well:

以及一个实现 draw 方法的类:

cSquare:

平方:

implements IDrawable 
Public Function draw()
    Debug.Print "Draw square method" 
End Function

We can switch between the implementations the following way:

我们可以通过以下方式在实现之间切换:

Dim square_1        As IDrawable

Set square_1 = New IDrawable
square_1.draw 'Draw interface method
Set square_1 = New cSquare
square_1.draw 'Draw square method    

This is not possible if you declare the variable as cSquare.
I can't immediately think of a good example when this might be useful, but it is technically possible if you test it.

如果将变量声明为 cSquare,则这是不可能的。
当这可能有用时,我无法立即想到一个很好的例子,但如果你测试它,它在技术上是可能的。

回答by Aleksey F.

There are two undocumented additions about VBA and "Implements" statement.

关于 VBA 和“Implements”语句,有两个未记录的补充。

  1. VBA does not support undescore character '_' in a method name of an inherited interface of a derived class. F.e. it will not compile a code with method such as cShape.get_area (tested under Excel 2007): VBA will output the compile error above for any derived class.

  2. If a derived class does not implement the own method named as in the interface, VBA compiles a code successfully, but the method will be inacessiable through a variable of the derived class type.

  1. VBA 不支持在派生类的继承接口的方法名称中使用下划线字符“_”。Fe 它不会使用诸如 cShape.get_area 之类的方法编译代码(在 Excel 2007 下测试):VBA 将为任何派生类输出上述编译错误。

  2. 如果派生类没有实现接口中名为 as 的自己的方法,VBA 可以成功编译代码,但是该方法将无法通过派生类类型的变量访问。

回答by Santosh

We must implement all methods of interface in the class which it is used.

我们必须在使用它的类中实现接口的所有方法。

cCircle Class

cCircle 类

Option Explicit
Implements cShape

Public myRadius As Double

Public Function getDiameter()
    getDiameter = 2 * myRadius
End Function

Public Function getArea()
    getArea = Application.WorksheetFunction.Pi() * (myRadius ^ 2)
End Function

''Inertia around the X axis
Public Function getInertiaX()
    getInertiaX = Application.WorksheetFunction.Pi() / 4 * (myRadius ^ 4)
End Function

''Inertia around the Y axis
''Ix = Iy in a circle, technically should use same function
Public Function getIntertiaY()
    getIntertiaY = Application.WorksheetFunction.Pi() / 4 * (myRadius ^ 4)
End Function

Public Function toString()
    toString = "This is a radius " & myRadius & " circle."
End Function

Private Function cShape_getArea() As Variant

End Function

Private Function cShape_getInertiaX() As Variant

End Function

Private Function cShape_getIntertiaY() As Variant

End Function

Private Function cShape_toString() As Variant

End Function

cRectangle Class

cRectangle 类

Option Explicit
Implements cShape

Public myLength As Double ''going to treat length as d
Public myWidth As Double ''going to treat width as b
Private getIntertiaX As Double

Public Function getArea()
    getArea = myLength * myWidth
End Function

Public Function getInertiaX()
    getIntertiaX = (myWidth) * (myLength ^ 3)
End Function

Public Function getIntertiaY()
    getIntertiaY = (myLength) * (myWidth ^ 3)
End Function

Public Function toString()
    toString = "This is a " & myWidth & " by " & myLength & " rectangle."
End Function

Private Function cShape_getArea() As Variant

End Function

Private Function cShape_getInertiaX() As Variant

End Function

Private Function cShape_getIntertiaY() As Variant

End Function

Private Function cShape_toString() As Variant

End Function

cShape Class

cShape 类

Option Explicit

Public Function getArea()
End Function

Public Function getInertiaX()
End Function

Public Function getIntertiaY()
End Function

Public Function toString()
End Function

enter image description here

在此处输入图片说明

回答by SlowLearner

Quick Fix of Syntax

语法的快速修复

If the interface ISomeInterfacehas:

如果接口ISomeInterface有:

Public Sub someMethod()
    ' Interface, no code
End Sub

Then the implementationneeds to be like:

然后实现需要像:

Implements ISomeInterface

Public Sub ISomeInterface_someMethod()
    '      ^^^^^^^^^^^^^^^  ' If missing: Compile Error 
    ' Code goes here
End Sub

A nice approach:

一个不错的方法:

Implements ISomeInterface

Private Sub someMethod()
    ' Business logic goes here
End Sub

Public Sub ISomeInterface_someMethod()
    someMethod ' i.e. Business logic in 1 place: someMethod
End Sub


That said, the other answers are very much worth reading.

也就是说,其他答案非常值得一读。

回答by hymced

Very interesting post to understand simply why and when an interface can be useful! But I think your final example about the default implementation is incorrect. The first call to the drawmethod of square_1 instantiated as IDrawable correctly prints the result you give, but the second call to the drawmethod of square_1 instantiated as cSquare is incorrect, nothing is printed. 3 different methods actually come into play:

非常有趣的帖子,可以简单地了解界面有用的原因和时间!但我认为你关于默认实现的最后一个例子是不正确的。对draw实例化为 IDrawable 的 square_1 方法的第一次调用正确打印了您给出的结果,但对draw实例化为 cSquare 的 square_1 方法的第二次调用不正确,没有打印任何内容。3种不同的方法实际上发挥作用:

IDrawable.cls:

IDrawable.cls:

Public Function draw()
    Debug.Print "Interface Draw method"
End Function

cSquare.cls:

cSquare.cls:

Implements IDrawable

Public Function draw()
    Debug.Print "Class Draw method"
End Function

Public Function IDrawable_draw()
    Debug.Print "Interfaced Draw method"
End Function

Standard module:

标准模块:

Sub Main()
    Dim square_1 As IDrawable
    Set square_1 = New IDrawable
    Debug.Print "square_1 : ";
    square_1.draw

    Dim square_2 As cSquare
    Set square_2 = New cSquare
    Debug.Print "square_2 : ";
    square_2.draw 

    Dim square_3 As IDrawable
    Set square_3 = New cSquare
    Debug.Print "square_3 : ";
    square_3.draw
End Sub

Results in:

结果是:

square_1 : Interface Draw method
square_2 : Class Draw method
square_3 : Interfaced Draw method