事件非常棒,我不知道没有它们会怎么做,但对我来说这是个谜。
我在谈论某种意义上的事件,如果属性或价值,特殊事件发生,则会调用函数。
我只有最简单的想法,这些实际上是如何工作的。我知道这是一个观察者模式,但我不知道它是如何工作的和/或如何实现它。
有人可以向我解释一下吗?
答案 0 :(得分:2)
答案 1 :(得分:2)
据我所知,你问的是事件是如何运作的。你还没有说明你要问的语言/平台,所以我会用我所知道的(.Net)来回答,虽然我确信很多平台都是相似的,但请记住我说的可能不是无处不在。
我将从最低级别开始并向上工作。
功能指针
在大多数语言中都有函数指针的概念。在像C ++这样的语言中,您可以逐字存储指向方法的内存地址的指针。在像Lisp或F#这样的函数式语言中,函数是关键,它是您可以存储和传递函数引用的语言的关键部分。在.net中,函数指针是使用委托实现的。
<强>代表强>
In .Net事件是使用代理实现的。 delegate是类型安全函数指针。它是指向函数的指针,仅限于特定类型,并在编译时根据该类型进行检查。您可以触发委托,并调用它指向的功能。
<强>组播强>
multicast delegate是一个形成代表集合的类。它在内部使用一个列表来存储多个委托。当您调用add
或执行+=
时,您只需将新的委托(函数指针)添加到多播的内部列表中。可以触发多播委托实例,它只是向下移动列表并按顺序在内部触发每个委托。
<强>事件强>
event只是一个关键字,它会在支持事件的多播委托之上添加一些额外的限制。例如(除其他事项外)在声明多播委托实例时使用event关键字限制它,以便只能从声明它的类中触发它。
所以,总结一下。事件只是一个函数指针列表。当您订阅简单时,将指向函数的指针添加到列表中。当事件被触发时,它只需向下移动列表并触发它知道的每个函数指针。
显然,正如我在开始时所说的那样,每种语言/环境都会有所不同,但如果维护一个简单的函数指针列表的想法可能相当普遍,我也不会感到惊讶。
如果这是您感兴趣的平台,Jon Skeet有一个很好的article on events in .Net,您应该阅读以获取更多信息。
答案 2 :(得分:0)
事件实际上非常简单。
首先,Object定义了其他对象可以订阅的事件。当Object注册一个Event时,Object存储一个在事件发生时将被调用的函数引用(或委托)。
接下来,感兴趣的Object通过将函数引用传递给Observable对象来订阅事件(该函数必须与Observable类提供的签名匹配)。
当事件发生时,Observable类调用适当的方法。
这是一个快速示例(在C#中):
// Specifies the signature for the event and stores the reference
public delegate void ChangedEventHandler(object sender, EventArgs e);
public class ObservableObject
{
// Creates an event called Changed using the signature provided by the
// delegate.
public event ChangedEventHandler Changed;
// This is the method we're interested in notifying subscribers about.
public void SomeInterestnigMethod()
{
// Something just changed, notify subscribers
Changed(this, new EventArgs());
}
}
然后在另一个想要订阅Changed事件的类中:
public class Observer
{
ObservableObject _obj = new ObservableObject();
public Observer()
{
// Pass the function reference to objChangedHandler to the
// Observable Object.
_obj.Changed += objChangedHandler;
}
public void objChangedHandler(object sender, EventArgs e)
{
// Handle the event here
}
}
答案 3 :(得分:0)
你的观察者需要一个接口(在接口关键字意义上不一定是例如java / c#) - 你需要以某种方式知道在需要时调用哪个方法 通知他们。观察者注册他们的兴趣并将它们添加到列表中。
每当你收到要通知的内容时,你都会查看观察者列表 在每个人上调用一个方法。当有人不想再收到通知时,只需将其从观察员名单中删除即可。
这是一个c#示例,不使用c#中的内置'events'或委托:
using System;
using System.Collections.Generic;
namespace ObserverTest
{
interface IInvestor
{
void Update(Stock stock);
}
abstract class Stock
{
private string _symbol;
private double _price;
private List<IInvestor> _investors = new List<IInvestor>();
// Constructor
public Stock(string symbol, double price)
{
this._symbol = symbol;
this._price = price;
}
public void Attach(IInvestor investor)
{
_investors.Add(investor);
}
public void Detach(IInvestor investor)
{
_investors.Remove(investor);
}
public void Notify()
{
foreach (IInvestor investor in _investors)
{
investor.Update(this);
}
Console.WriteLine("");
}
public double Price
{
get { return _price; }
set
{
if (_price != value)
{
_price = value;
Notify();
}
}
}
public string Symbol
{
get { return _symbol; }
}
}
class IBM : Stock
{
public IBM(string symbol, double price)
: base(symbol, price)
{
}
}
class Investor : IInvestor
{
private string _name;
// Constructor
public Investor(string name)
{
this._name = name;
}
public void Update(Stock stock)
{
Console.WriteLine("Notified {0} of {1}'s " +
"change to {2:C}", _name, stock.Symbol, stock.Price);
}
}
class MainApp
{
static void Main()
{
IBM ibm = new IBM("IBM", 120.00);
ibm.Attach(new Investor("Sorros"));
ibm.Attach(new Investor("Berkshire"));
ibm.Price = 120.10;
ibm.Price = 121.00;
ibm.Price = 120.50;
ibm.Price = 120.75;
Console.ReadKey();
}
}
}