Как сравнить два экземпляра класса - PullRequest
0 голосов
/ 08 октября 2009

Допустим, я создал класс с именем Store. Этот класс имеет несколько элементов, таких как Name, PhoneNumber, Owner.

Я создал 2 экземпляра этого класса и хочу знать, какие значения отличаются.

Итак, допустим, что Store1 и Store2 являются экземплярами этого класса.

Store1.Name = "John's Corner";  
Store1.PhoneNumber = 111222333;  
Store1.Owner = "John";  

Store2.Name = "John's Corner";  
Store2.PhoneNumber = 444555666;  
Store2.Owner = "John";  

Обычно для сравнения можно сделать:

if (Store1.Name == Store2.Name) output.text += "Store name is different."  
if (Store1.PhoneNumber == Store2.PhoneNumber) output.text += "Store Phone Number is different."  
if (Store1.Owner == Store2.Owner) output.text += "Store Owner is different."

Есть ли способ автоматически перебирать все элементы экземпляра класса, сравнивать их с одним и тем же элементом в другом экземпляре класса и возвращать что-то, когда они различаются?

Это может быть очевидно, но я не могу понять это.

Ответы [ 5 ]

2 голосов
/ 08 октября 2009

Для закрытых свойств вы можете описать тип, затем цикл в его аксессорах:

var typeXML:XML = describeType(Store1);
var diffs:Dictionary = new Dictionary();
for each(var prop:XML in type..accessor){
     if(Store1[prop] != Store2[prop]){
          diffs[prop] = new Array(Store1[prop],Store2[prop]);
     }
}

Извините, передо мной нет компилятора, поэтому я не могу ничего проверить. Взгляните на объект typeXML, чтобы увидеть, что вам нужно зациклить в цикле for.

0 голосов
/ 09 октября 2009

Просто сериализуйте оба объекта в строку JSON и сравните строку.

0 голосов
/ 08 октября 2009

Если вам не нужно полностью универсальное решение (сколько классов вы собираетесь сравнить?), Напишите пользовательскую функцию compare в соответствующем классе, которая проходит через свойства класса и возвращает логическое значение.

Обновление:
Спасибо Дэн за describeType. Осторожно, чтобы описать descriptionType, он отражает только открытые переменные / свойства класса. Приватный / защищенный / внутренний материал не включен в выходные данные descriptionType. Следовательно, если вы используете его для сравнения двух объектов, имеющих одинаковые общие свойства, но разные частные свойства, он все равно скажет вам, что они равны.

Вот класс AS и его вывод descriptionType. Data.as

package
{
    public class Data
    {
        private var privateVar:Boolean;
        protected var protectedVar:Boolean;
        internal var internalVar:Boolean;
        var noModifierVar:Boolean;
        public var publicVar:Boolean;

        public function set writeOnlyProp(value:Boolean):void
        {
        }

        public function get readOnlyProp():Boolean
        {
            return true;
        }

        public function set readWriteProp(value:Boolean):void
        {

        }
        public function get readWriteProp():Boolean
        {
            return false;
        }

        public function Data(pub:Boolean = false, priv:Boolean = false, 
            prot:Boolean = false, inter:Boolean = false)
        {
            this.privateVar = priv;
            this.protectedVar = prot;
            this.internalVar = inter;
            this.publicVar = pub;
        }
    }
}

Вывод describeType: обратите внимание, что здесь перечислены только публичные переменные.

<type name="Data" base="Object" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="Object"/>
  <constructor>
    <parameter index="1" type="Boolean" optional="true"/>
    <parameter index="2" type="Boolean" optional="true"/>
    <parameter index="3" type="Boolean" optional="true"/>
    <parameter index="4" type="Boolean" optional="true"/>
  </constructor>
  <accessor name="readOnlyProp" access="readonly" type="Boolean" declaredBy="Data"/>
  <variable name="publicVar" type="Boolean"/>
  <accessor name="readWriteProp" access="readwrite" type="Boolean" declaredBy="Data"/>
  <accessor name="writeOnlyProp" access="writeonly" type="Boolean" declaredBy="Data"/>
</type>

Общий код сравнения будет выглядеть так:

public static function compareObjects(a:Object, b:Object):Boolean
{
    var description:XML = describeType(a);
    var bDescription:XML = describeType(b);
    //different classes
    if(description.toXMLString() != bDescription.toXMLString())
        return false;
    if(String(description.@isDynamic) == "true")
    {
        var t:*;
        for(t in a)
            if(a[t] != b[t])
                return false;
        //Just in case b has a dynamic property that a doesn't
        for(t in b)
            if(a[t] != b[t])
                return false;
    } 
    var properties:Array = [];
    //readonly and readwrite properties
    var accessors:XMLList = description.accessor.(@access != "writeonly");
    var type:XML;
    for each(type in accessors)
        properties.push(String(type.@name));
    //other variables
    var variables:XMLList = description.variable;
    for each(type in variables)
        properties.push(String(type.@name));
    for each(var prop:String in properties)
    {
        if(a[prop] != b[prop])
            return false;
    }
    return true;
}

PS: После написания всего этого кода я все еще чувствую, что написание собственного кода в соответствующем классе - правильный путь, так как это не учитывает личные / защищенные данные.

0 голосов
/ 08 октября 2009

Следуя коду Джеймса, вы можете изменить первую строку следующим образом:

for (var property in ["property1","property2","property3")

Если вам нужно сделать это динамически, вы можете использовать descriptionType , чтобы получить все открытые свойства класса.

0 голосов
/ 08 октября 2009

1001 * попробовать *

for (var property in Store1)
{
   if (Store1[property] == Store2[property])
   {
      trace("property-" + property + ", value-" + Store1[property]);
   }
}

Очевидно, что это не сработает, если хранилище 1 и два разных типов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...