【问题标题】:Swift "Protocol type 'AnyObject' cannot be instantiated" error while returning to AnyObject返回 AnyObject 时出现 Swift“无法实例化协议类型‘AnyObject’”错误
【发布时间】:2020-09-17 08:08:23
【问题描述】:

我正在尝试在 Swift 上编写以下 Java 代码。

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch; // these fields are used across all the methods

        void nextChar() {
             // ...
        }

        boolean eat(int charToEat) {
            // ...
            // calls nextChar somewhere
        }

        double parse() {
            // ...
            // calls nextChar and parseExpression somewhere
        }

        double parseExpression() {
            // ...
            // calls parseTerm somewhere
        }

        double parseTerm() {
            // ...
            // calls parseFactor somewhere
        }

        double parseFactor() {
            // ...
            // recursively calls parseFactor and parseExpression somewhere
        }
    }.parse();
}

我在 Swift 上遇到了“无法实例化协议类型'AnyObject'”的问题。我的 Swift 代码如下。我怎样才能实现这种转换?我的意思是,如何在 Swift 上将函数返回给任何对象?

func eval(str: String) -> Double {
    return AnyObject {             //Here it says "Protocol type 'AnyObject' cannot be instantiated"
       ...
       func parse() -> Double {
           ...
       }
    }.parse()
}

为了清楚起见,我在上面简要地写了,但是当我看到答案时,最好发布整个代码。下面提供了快速代码。我正在研究 Boann 在 url https://stackoverflow.com/a/26227947/12698480 上提供的计算器代码

【问题讨论】:

  • 这与您几天前发布的几乎完全相同的问题,而不是发布一些 java 代码作为答案,您不能用语言解释您的函数应该做什么,它是什么你正在努力实现?
  • 如果您可以显示第一个 ....... (some code) 包含的代码,我可以提供更有用的答案。
  • @Sweeper 我在第一篇文章中添加了整个代码,你现在可以看看吗?
  • @JoakimDanielson 我在帖子中添加了整个代码,你现在可以看一下吗?
  • 查看更新后的答案。我已对您的问题进行了编辑,以包含您的问题所需的最少信息,以免过于宽泛。

标签: swift type-conversion


【解决方案1】:

您对 Java 代码的翻译过于字面化了。我们首先应该了解Java代码是做什么的,为什么作者会这样写。

Java 代码所做的是创建一个“内联”类,并立即调用其中一个方法。该类有很多方法和状态,方法会改变状态并递归调用对方。 IMO,它确实应该被移到一个命名类中,但作者可能认为这是唯一会使用它的地方,所以他们做了“内联”。

你可以在 Swift 中直接嵌套函数,所以你可以忽略 new Object 部分,直接做:

func eval(str: String) -> Double {
    var pos = -1
    var ch = -1

    func nextChar() {
         // ...
    }

    func eat(charToEat: Int) -> Bool {
        // ...
    }

    func parse() -> Double {
        // ...
    }

    func parseExpression() -> Double {
        // ...
    }

    func parseTerm() -> Double {
        // ...
    }

    func parseFactor() -> Double {
        // ...
    }
    
    return parse()
}

但是,当它有这么多方法和这么复杂时,我只会创建一个类/结构:

struct Parser {
    var str: String
    // put everything declared in eval here
}

eval,执行:

Parser(str: str).parse()

【讨论】:

  • 感谢@Sweeper 的快速和一步一步的非常清晰的理解帮助,我真的很感激!现在我会尝试你所有的建议,我希望我能实现,因为我有点新:)
  • “IMO,它真的应该被移动到一个命名类中” 是的,我同意,但我的理由是我试图保持它自包含,以便于复制粘贴和重用。
【解决方案2】:

由于错误状态AnyObject 是协议/类型别名(Java 中称为接口)而不是具体类型。这意味着您不能直接实例化它,因为编译器不知道实际类型是什么。 考虑以下示例:

protocol Animal {
    var name: String { get }
    var height: Double { get }
}

然后您添加一些不同的动物类型,它们可能出于某种原因执行一些自定义逻辑:

struct Dog: Animal {
    let name: String
    let height: Double
}

struct Cat: Animal {
    let name: String
    let height: Double
}

然后你可以像这样使用它:

var myPet: Animal?
myPet = Cat(name: "Scratchy", height: 20.2)
myPet = Dog(name: "Barky", height: 53.8)

这可以正确编译,因为您没有尝试直接实例化 Animal 类型的对象,而是创建了一个“占位符”。您现在可以将任何符合 Animal 的对象分配给它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2023-02-10
    • 2014-10-23
    • 2015-01-02
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多