2017-06-12 123 views
0

我有一个函数,它需要一个类型为Being的实例。有Being有两个亚类:PersonAnimal。我希望函数能够识别哪个被传递,并且针对每个子类使用特定的属性。将超类作为其中一个子类投射

我想这会工作:

func fight(attacker1: Being, attacker2: Being) -> String { 
    if attacker1 is Person { 
     let name1 = attacker1.name as! Person //Error: Value of type Being has no member name 
    } else { 
     print("Its not a person") 
    } 

但事实并非如此。什么是最顺利/最短的方式来实现我在找什么?

+0

在这种情况下,为什么不使用基类中的名字? (因为动物和人都可以有名字) – giorashc

+0

'attacker1.name as!人'这是错误的,请看[V.Khambirs'Ans](https://stackoverflow.com/a/44493238/5546312) – D4ttatraya

+0

@giorashc他们不能。它是名称或物种。根据交给该职能的班级,它需要知道要求哪一个。 – Marmelador

回答

1

尽管@ V.Khambir的代码有效,可能是更好的解决方案,但并没有指出你的代码问题。您正试图将.name转换为Person.name不是attacker1的财产,这就是为什么你会收到错误。你想要做的是投attacker1Person,然后访问名称属性。

func fight(attacker1: Being, attacker2: Being) -> String { 
    if attacker1 is Person { 
     let name1 = (attacker1 as! Person).name 
    } else { 
     print("Its not a person") 
    } 
+0

由于这个答案更具体地代表我的问题,我已经标记为正确的。 – Marmelador

+0

这不会使用Swift最佳实践,因为您实际上正在执行两次......一次在检查中,然后再次访问名称属性。在这里使用if-let语法的其他答案实际上是你应该标记的那个,因为这个转换只能做一次,再加上你的子类的强类型变量,所以不需要进一步转换。 – MarqueIV

+0

我完全同意你的看法!我不喜欢我的代码示例,也喜欢V.Khambir的代码示例。这就是为什么我写了第一句话。但是,我想指出Marmelador的代码问题。 – Yannick

6

您应该创建所需类型的新变量并将参数放入此变量中。

func fight(attacker1: Being, attacker2: Being) -> String { 
    if let att1 = attacker1 as? Person { 
     let name1 = att1.name 
    } else { 
     print("Its not a person") 
    } 

这样,如果attacker1是人,你只是保存该数值到ATT1不变,以后你可以用这个常量作为类型的实例。

0

由于存在是一个基类,所以它将无法访问任何子类属性。所以首先,你必须检查攻击者1和攻击者2的类型。例如:如果攻击者1的类型是Person,那么你可以将它转换为Person类型的实例,然后访问person对象的属性。 注意: - 确保首先检查类型,然后键入cast,否则会崩溃。

相关问题