我尝试使用参考比较(===
)比较两种协议类型。当我这样做时(Foo
是一个协议):
Binary operator '===' cannot be applied to two 'Foo' operands
我理解为什么==
won't work without conforming to Equatable
,但在这种情况下,我使用===
,这只是一个地址比较。
答案 0 :(得分:8)
让我们在声明中显示问题:
===
运算符已声明为AnyObject
。
public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
究竟是什么AnyObject
? AnyObject
是所有类自动符合的协议。
在Swift中,不仅有类类型,还有值类型,例如结构和枚举。所有这些都符合协议,但结构和枚举不符合AnyObject
。由于您具有Java背景,因此值类型的行为类似于Java中的基本类型 - 它们通过值(复制)传递,并且通常不会引用它们。
当您声明协议时,编译器不知道它是否会被类或结构采用。
protocol X {}
struct A: X {}
let x1: X = A()
let x2: X = A()
// PROBLEM - we cannot compare two structs by ===
if x1 === x2 {
}
这意味着我们必须告诉编译器该协议只能由类采用:
protocol X: AnyObject {}
或
protocol X: class {}
然后
class A: X {} // can be adopted only by classes
let x1: X = A()
let x2: X = A()
// NO problem
if x1 === x2 {
}
答案 1 :(得分:3)
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tag");
//Acquire the lock
wl.acquire();
Log.v("ADebugTag", "It work!");
int mId = 0;
//Show the notification here.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_action_edit)
.setContentTitle("Diario Scolastico")
.setContentText("You have homeworks for tomorrow!")
.setAutoCancel(true)
.setDefaults(-1);
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(context, MainActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(mId, mBuilder.build());
//Release the lock
wl.release();
}
}
比较器用于比较引用 - 因为结构是值类型,它们通过值传递并且没有引用。 (基本上传递一个结构只需要一个副本)
类是通过引用传递的 - 实例存储在内存中,因此您可以使用<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
比较器。
所以是的,您可以比较它们,但您需要确保协议仅限于类。
e.g。
===
其中
===
将无法编译
答案 2 :(得分:-6)
使用===你可以比较两个对某些实例的引用,但协议类型无法实例化!
protocol P {}
class C: P{}
let c = C()
let p:P = C()
c.dynamicType // C.Type
p.dynamicType // C.Type
和
let p:P = P() // error !!!
您可以告诉编译器您的协议是类协议
protocol P: class {}
class C: P{}
struct S: P{} // error: non-class type 'S' cannot conform to class protocol 'P'
确保没有符合它的值类型
见最后一个例子
protocol P: class {}
class C: P{}
let c = C()
let p:P = c
p === c // true !!
let p1:P = c
p === p1 // true !!!
===运算符在这里工作
let c1 = C()
let p2:P = c1
p2 === p1 // false !!