1) я его расширил от EventDispatcher на автомате, т.к. если бы я писал полноценный класс, я бы сделал еще и отправку собственного события COMPLETE в момент когда закончилось проигрывание анимации. Т.е. что бы иметь возможность вызвать метод dispatchEvent, нужно наследоваться от класса EventDispatcher(или его наследника, или класса реализующего интерфейс IEventDispatcher).
Нет смысла наследоваться от Sprite потому, что класс PlayerMC не является визуальным, т.е. нам не нужно добавлять его на stage методом addChild(...), и поэтому нет смысла расширять его от класса Sprite.
Если все таки унаследоваться от класса Sprite - то ошибки не будет, т.к. Sprite является наследником класса EventDispatcher, см внимательно
документацию:
2) Написал метод stop только ради чистоты кода, что бы класс PlayerMC имел методы не только для начала проигрывания, но и для остановки проигрывания в любой момент из класса Main. Override здесь писать не нужно, потому что класс PlayerMC наследуется от класса EventDispatcher, а этот класс EventDispatcher не имеет метода stop. Вот если бы вы написали PlayerMC extends MovieClip, тогда пришлось бы писать override, т.к. у базового класса есть метод stop()
3) "В обоих одинаковые ремув-листенеры... зачем так?" - это затем, что первый вызывается после окончания проигрывания системой, а метод stop можно вызывать из Main-а что бы принудительно остановить проигрывание в любой момент. Можно было бы написать в обработчике frameHandler вызов метода stop, но это плохая практика, лучше изолировать код который выполняется внутри класса, от методов которые вызываются снаружи. Если очень хочется объединить два одинаковых кода, можно написать еще один private метод stopAnimation:

Код AS3:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
public class PlayerMC extends EventDispatcher
{
private var mc:MovieClip;
public function PlayerMC(mc:MovieClip)
{
this.mc = mc;
mc.stop();
}
private var totalCount:uint;
private var currentCount:uint;
private function frameHandler(event:Event):void
{
if (mc.currentFrame == mc.totalFrames) {
currentCount++;
}
if (currentCount == totalCount) {
stopAnimation();
this.dispatchEvent(new Event('completeAnim'));
}
}
private function stopAnimation():void
{
mc.stop();
mc.removeEventListener(Event.ENTER_FRAME, frameHandler);
}
public function playAmount(count:uint=1):void
{
this.totalCount = count;
this.currentCount = 0;
//
mc.addEventListener(Event.ENTER_FRAME, frameHandler);
mc.play();
}
public function stop():void
{
stopAnimation();
this.dispatchEvent(new Event('stopAnim'));
}
}
}
В этом коде я показал пример зачем необходимо изолировать внутренний вызов от внешнего: в примере выше генерируются два события: stopAnim - в момент когда вызываем метод stop из вне, и событие completeAnim в момент когда проигрывание дошло до конца и остановилось.