Swift - 二元运算符' ==='不能应用于两个协议

时间:2016-01-02 18:21:51

标签: swift

我尝试使用参考比较(===)比较两种协议类型。当我这样做时(Foo是一个协议):

Binary operator '===' cannot be applied to two 'Foo' operands

我理解为什么== won't work without conforming to Equatable,但在这种情况下,我使用===,这只是一个地址比较。

3 个答案:

答案 0 :(得分:8)

让我们在声明中显示问题:

===运算符已声明为AnyObject

public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool

究竟是什么AnyObjectAnyObject是所有类自动符合的协议。

在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 !!